1b7579f77SDag-Erling Smørgrav /* 2b7579f77SDag-Erling Smørgrav * util/net_help.c - implementation of the network helper code 3b7579f77SDag-Erling Smørgrav * 4b7579f77SDag-Erling Smørgrav * Copyright (c) 2007, NLnet Labs. All rights reserved. 5b7579f77SDag-Erling Smørgrav * 6b7579f77SDag-Erling Smørgrav * This software is open source. 7b7579f77SDag-Erling Smørgrav * 8b7579f77SDag-Erling Smørgrav * Redistribution and use in source and binary forms, with or without 9b7579f77SDag-Erling Smørgrav * modification, are permitted provided that the following conditions 10b7579f77SDag-Erling Smørgrav * are met: 11b7579f77SDag-Erling Smørgrav * 12b7579f77SDag-Erling Smørgrav * Redistributions of source code must retain the above copyright notice, 13b7579f77SDag-Erling Smørgrav * this list of conditions and the following disclaimer. 14b7579f77SDag-Erling Smørgrav * 15b7579f77SDag-Erling Smørgrav * Redistributions in binary form must reproduce the above copyright notice, 16b7579f77SDag-Erling Smørgrav * this list of conditions and the following disclaimer in the documentation 17b7579f77SDag-Erling Smørgrav * and/or other materials provided with the distribution. 18b7579f77SDag-Erling Smørgrav * 19b7579f77SDag-Erling Smørgrav * Neither the name of the NLNET LABS nor the names of its contributors may 20b7579f77SDag-Erling Smørgrav * be used to endorse or promote products derived from this software without 21b7579f77SDag-Erling Smørgrav * specific prior written permission. 22b7579f77SDag-Erling Smørgrav * 23b7579f77SDag-Erling Smørgrav * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24b7579f77SDag-Erling Smørgrav * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 25b7579f77SDag-Erling Smørgrav * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 26b7579f77SDag-Erling Smørgrav * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE 27b7579f77SDag-Erling Smørgrav * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 28b7579f77SDag-Erling Smørgrav * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 29b7579f77SDag-Erling Smørgrav * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 30b7579f77SDag-Erling Smørgrav * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 31b7579f77SDag-Erling Smørgrav * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 32b7579f77SDag-Erling Smørgrav * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 33b7579f77SDag-Erling Smørgrav * POSSIBILITY OF SUCH DAMAGE. 34b7579f77SDag-Erling Smørgrav */ 35b7579f77SDag-Erling Smørgrav /** 36b7579f77SDag-Erling Smørgrav * \file 37b7579f77SDag-Erling Smørgrav * Implementation of net_help.h. 38b7579f77SDag-Erling Smørgrav */ 39b7579f77SDag-Erling Smørgrav 40b7579f77SDag-Erling Smørgrav #include "config.h" 41b7579f77SDag-Erling Smørgrav #include <ldns/ldns.h> 42b7579f77SDag-Erling Smørgrav #include "util/net_help.h" 43b7579f77SDag-Erling Smørgrav #include "util/log.h" 44b7579f77SDag-Erling Smørgrav #include "util/data/dname.h" 45b7579f77SDag-Erling Smørgrav #include "util/module.h" 46b7579f77SDag-Erling Smørgrav #include "util/regional.h" 47b7579f77SDag-Erling Smørgrav #include <fcntl.h> 48*8ed2b524SDag-Erling Smørgrav #ifdef HAVE_OPENSSL_SSL_H 49b7579f77SDag-Erling Smørgrav #include <openssl/ssl.h> 50*8ed2b524SDag-Erling Smørgrav #endif 51*8ed2b524SDag-Erling Smørgrav #ifdef HAVE_OPENSSL_ERR_H 52b7579f77SDag-Erling Smørgrav #include <openssl/err.h> 53*8ed2b524SDag-Erling Smørgrav #endif 54b7579f77SDag-Erling Smørgrav 55b7579f77SDag-Erling Smørgrav /** max length of an IP address (the address portion) that we allow */ 56b7579f77SDag-Erling Smørgrav #define MAX_ADDR_STRLEN 128 /* characters */ 57b7579f77SDag-Erling Smørgrav /** default value for EDNS ADVERTISED size */ 58b7579f77SDag-Erling Smørgrav uint16_t EDNS_ADVERTISED_SIZE = 4096; 59b7579f77SDag-Erling Smørgrav 60b7579f77SDag-Erling Smørgrav /** minimal responses when positive answer: default is no */ 61b7579f77SDag-Erling Smørgrav int MINIMAL_RESPONSES = 0; 62b7579f77SDag-Erling Smørgrav 63b7579f77SDag-Erling Smørgrav /** rrset order roundrobin: default is no */ 64b7579f77SDag-Erling Smørgrav int RRSET_ROUNDROBIN = 0; 65b7579f77SDag-Erling Smørgrav 66b7579f77SDag-Erling Smørgrav /* returns true is string addr is an ip6 specced address */ 67b7579f77SDag-Erling Smørgrav int 68b7579f77SDag-Erling Smørgrav str_is_ip6(const char* str) 69b7579f77SDag-Erling Smørgrav { 70b7579f77SDag-Erling Smørgrav if(strchr(str, ':')) 71b7579f77SDag-Erling Smørgrav return 1; 72b7579f77SDag-Erling Smørgrav else return 0; 73b7579f77SDag-Erling Smørgrav } 74b7579f77SDag-Erling Smørgrav 75b7579f77SDag-Erling Smørgrav int 76b7579f77SDag-Erling Smørgrav fd_set_nonblock(int s) 77b7579f77SDag-Erling Smørgrav { 78b7579f77SDag-Erling Smørgrav #ifdef HAVE_FCNTL 79b7579f77SDag-Erling Smørgrav int flag; 80b7579f77SDag-Erling Smørgrav if((flag = fcntl(s, F_GETFL)) == -1) { 81b7579f77SDag-Erling Smørgrav log_err("can't fcntl F_GETFL: %s", strerror(errno)); 82b7579f77SDag-Erling Smørgrav flag = 0; 83b7579f77SDag-Erling Smørgrav } 84b7579f77SDag-Erling Smørgrav flag |= O_NONBLOCK; 85b7579f77SDag-Erling Smørgrav if(fcntl(s, F_SETFL, flag) == -1) { 86b7579f77SDag-Erling Smørgrav log_err("can't fcntl F_SETFL: %s", strerror(errno)); 87b7579f77SDag-Erling Smørgrav return 0; 88b7579f77SDag-Erling Smørgrav } 89b7579f77SDag-Erling Smørgrav #elif defined(HAVE_IOCTLSOCKET) 90b7579f77SDag-Erling Smørgrav unsigned long on = 1; 91b7579f77SDag-Erling Smørgrav if(ioctlsocket(s, FIONBIO, &on) != 0) { 92b7579f77SDag-Erling Smørgrav log_err("can't ioctlsocket FIONBIO on: %s", 93b7579f77SDag-Erling Smørgrav wsa_strerror(WSAGetLastError())); 94b7579f77SDag-Erling Smørgrav } 95b7579f77SDag-Erling Smørgrav #endif 96b7579f77SDag-Erling Smørgrav return 1; 97b7579f77SDag-Erling Smørgrav } 98b7579f77SDag-Erling Smørgrav 99b7579f77SDag-Erling Smørgrav int 100b7579f77SDag-Erling Smørgrav fd_set_block(int s) 101b7579f77SDag-Erling Smørgrav { 102b7579f77SDag-Erling Smørgrav #ifdef HAVE_FCNTL 103b7579f77SDag-Erling Smørgrav int flag; 104b7579f77SDag-Erling Smørgrav if((flag = fcntl(s, F_GETFL)) == -1) { 105b7579f77SDag-Erling Smørgrav log_err("cannot fcntl F_GETFL: %s", strerror(errno)); 106b7579f77SDag-Erling Smørgrav flag = 0; 107b7579f77SDag-Erling Smørgrav } 108b7579f77SDag-Erling Smørgrav flag &= ~O_NONBLOCK; 109b7579f77SDag-Erling Smørgrav if(fcntl(s, F_SETFL, flag) == -1) { 110b7579f77SDag-Erling Smørgrav log_err("cannot fcntl F_SETFL: %s", strerror(errno)); 111b7579f77SDag-Erling Smørgrav return 0; 112b7579f77SDag-Erling Smørgrav } 113b7579f77SDag-Erling Smørgrav #elif defined(HAVE_IOCTLSOCKET) 114b7579f77SDag-Erling Smørgrav unsigned long off = 0; 115b7579f77SDag-Erling Smørgrav if(ioctlsocket(s, FIONBIO, &off) != 0) { 116b7579f77SDag-Erling Smørgrav log_err("can't ioctlsocket FIONBIO off: %s", 117b7579f77SDag-Erling Smørgrav wsa_strerror(WSAGetLastError())); 118b7579f77SDag-Erling Smørgrav } 119b7579f77SDag-Erling Smørgrav #endif 120b7579f77SDag-Erling Smørgrav return 1; 121b7579f77SDag-Erling Smørgrav } 122b7579f77SDag-Erling Smørgrav 123b7579f77SDag-Erling Smørgrav int 124b7579f77SDag-Erling Smørgrav is_pow2(size_t num) 125b7579f77SDag-Erling Smørgrav { 126b7579f77SDag-Erling Smørgrav if(num == 0) return 1; 127b7579f77SDag-Erling Smørgrav return (num & (num-1)) == 0; 128b7579f77SDag-Erling Smørgrav } 129b7579f77SDag-Erling Smørgrav 130b7579f77SDag-Erling Smørgrav void* 131b7579f77SDag-Erling Smørgrav memdup(void* data, size_t len) 132b7579f77SDag-Erling Smørgrav { 133b7579f77SDag-Erling Smørgrav void* d; 134b7579f77SDag-Erling Smørgrav if(!data) return NULL; 135b7579f77SDag-Erling Smørgrav if(len == 0) return NULL; 136b7579f77SDag-Erling Smørgrav d = malloc(len); 137b7579f77SDag-Erling Smørgrav if(!d) return NULL; 138b7579f77SDag-Erling Smørgrav memcpy(d, data, len); 139b7579f77SDag-Erling Smørgrav return d; 140b7579f77SDag-Erling Smørgrav } 141b7579f77SDag-Erling Smørgrav 142b7579f77SDag-Erling Smørgrav void 143b7579f77SDag-Erling Smørgrav log_addr(enum verbosity_value v, const char* str, 144b7579f77SDag-Erling Smørgrav struct sockaddr_storage* addr, socklen_t addrlen) 145b7579f77SDag-Erling Smørgrav { 146b7579f77SDag-Erling Smørgrav uint16_t port; 147b7579f77SDag-Erling Smørgrav const char* family = "unknown"; 148b7579f77SDag-Erling Smørgrav char dest[100]; 149b7579f77SDag-Erling Smørgrav int af = (int)((struct sockaddr_in*)addr)->sin_family; 150b7579f77SDag-Erling Smørgrav void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr; 151b7579f77SDag-Erling Smørgrav if(verbosity < v) 152b7579f77SDag-Erling Smørgrav return; 153b7579f77SDag-Erling Smørgrav switch(af) { 154b7579f77SDag-Erling Smørgrav case AF_INET: family="ip4"; break; 155b7579f77SDag-Erling Smørgrav case AF_INET6: family="ip6"; 156b7579f77SDag-Erling Smørgrav sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr; 157b7579f77SDag-Erling Smørgrav break; 158b7579f77SDag-Erling Smørgrav case AF_UNIX: family="unix"; break; 159b7579f77SDag-Erling Smørgrav default: break; 160b7579f77SDag-Erling Smørgrav } 161b7579f77SDag-Erling Smørgrav if(inet_ntop(af, sinaddr, dest, (socklen_t)sizeof(dest)) == 0) { 162b7579f77SDag-Erling Smørgrav strncpy(dest, "(inet_ntop error)", sizeof(dest)); 163b7579f77SDag-Erling Smørgrav } 164b7579f77SDag-Erling Smørgrav dest[sizeof(dest)-1] = 0; 165b7579f77SDag-Erling Smørgrav port = ntohs(((struct sockaddr_in*)addr)->sin_port); 166b7579f77SDag-Erling Smørgrav if(verbosity >= 4) 167b7579f77SDag-Erling Smørgrav verbose(v, "%s %s %s port %d (len %d)", str, family, dest, 168b7579f77SDag-Erling Smørgrav (int)port, (int)addrlen); 169b7579f77SDag-Erling Smørgrav else verbose(v, "%s %s port %d", str, dest, (int)port); 170b7579f77SDag-Erling Smørgrav } 171b7579f77SDag-Erling Smørgrav 172b7579f77SDag-Erling Smørgrav int 173b7579f77SDag-Erling Smørgrav extstrtoaddr(const char* str, struct sockaddr_storage* addr, 174b7579f77SDag-Erling Smørgrav socklen_t* addrlen) 175b7579f77SDag-Erling Smørgrav { 176b7579f77SDag-Erling Smørgrav char* s; 177b7579f77SDag-Erling Smørgrav int port = UNBOUND_DNS_PORT; 178b7579f77SDag-Erling Smørgrav if((s=strchr(str, '@'))) { 179b7579f77SDag-Erling Smørgrav char buf[MAX_ADDR_STRLEN]; 180b7579f77SDag-Erling Smørgrav if(s-str >= MAX_ADDR_STRLEN) { 181b7579f77SDag-Erling Smørgrav return 0; 182b7579f77SDag-Erling Smørgrav } 183b7579f77SDag-Erling Smørgrav strncpy(buf, str, MAX_ADDR_STRLEN); 184b7579f77SDag-Erling Smørgrav buf[s-str] = 0; 185b7579f77SDag-Erling Smørgrav port = atoi(s+1); 186b7579f77SDag-Erling Smørgrav if(port == 0 && strcmp(s+1,"0")!=0) { 187b7579f77SDag-Erling Smørgrav return 0; 188b7579f77SDag-Erling Smørgrav } 189b7579f77SDag-Erling Smørgrav return ipstrtoaddr(buf, port, addr, addrlen); 190b7579f77SDag-Erling Smørgrav } 191b7579f77SDag-Erling Smørgrav return ipstrtoaddr(str, port, addr, addrlen); 192b7579f77SDag-Erling Smørgrav } 193b7579f77SDag-Erling Smørgrav 194b7579f77SDag-Erling Smørgrav 195b7579f77SDag-Erling Smørgrav int 196b7579f77SDag-Erling Smørgrav ipstrtoaddr(const char* ip, int port, struct sockaddr_storage* addr, 197b7579f77SDag-Erling Smørgrav socklen_t* addrlen) 198b7579f77SDag-Erling Smørgrav { 199b7579f77SDag-Erling Smørgrav uint16_t p; 200b7579f77SDag-Erling Smørgrav if(!ip) return 0; 201b7579f77SDag-Erling Smørgrav p = (uint16_t) port; 202b7579f77SDag-Erling Smørgrav if(str_is_ip6(ip)) { 203b7579f77SDag-Erling Smørgrav char buf[MAX_ADDR_STRLEN]; 204b7579f77SDag-Erling Smørgrav char* s; 205b7579f77SDag-Erling Smørgrav struct sockaddr_in6* sa = (struct sockaddr_in6*)addr; 206b7579f77SDag-Erling Smørgrav *addrlen = (socklen_t)sizeof(struct sockaddr_in6); 207b7579f77SDag-Erling Smørgrav memset(sa, 0, *addrlen); 208b7579f77SDag-Erling Smørgrav sa->sin6_family = AF_INET6; 209b7579f77SDag-Erling Smørgrav sa->sin6_port = (in_port_t)htons(p); 210b7579f77SDag-Erling Smørgrav if((s=strchr(ip, '%'))) { /* ip6%interface, rfc 4007 */ 211b7579f77SDag-Erling Smørgrav if(s-ip >= MAX_ADDR_STRLEN) 212b7579f77SDag-Erling Smørgrav return 0; 213b7579f77SDag-Erling Smørgrav strncpy(buf, ip, MAX_ADDR_STRLEN); 214b7579f77SDag-Erling Smørgrav buf[s-ip]=0; 215b7579f77SDag-Erling Smørgrav sa->sin6_scope_id = (uint32_t)atoi(s+1); 216b7579f77SDag-Erling Smørgrav ip = buf; 217b7579f77SDag-Erling Smørgrav } 218b7579f77SDag-Erling Smørgrav if(inet_pton((int)sa->sin6_family, ip, &sa->sin6_addr) <= 0) { 219b7579f77SDag-Erling Smørgrav return 0; 220b7579f77SDag-Erling Smørgrav } 221b7579f77SDag-Erling Smørgrav } else { /* ip4 */ 222b7579f77SDag-Erling Smørgrav struct sockaddr_in* sa = (struct sockaddr_in*)addr; 223b7579f77SDag-Erling Smørgrav *addrlen = (socklen_t)sizeof(struct sockaddr_in); 224b7579f77SDag-Erling Smørgrav memset(sa, 0, *addrlen); 225b7579f77SDag-Erling Smørgrav sa->sin_family = AF_INET; 226b7579f77SDag-Erling Smørgrav sa->sin_port = (in_port_t)htons(p); 227b7579f77SDag-Erling Smørgrav if(inet_pton((int)sa->sin_family, ip, &sa->sin_addr) <= 0) { 228b7579f77SDag-Erling Smørgrav return 0; 229b7579f77SDag-Erling Smørgrav } 230b7579f77SDag-Erling Smørgrav } 231b7579f77SDag-Erling Smørgrav return 1; 232b7579f77SDag-Erling Smørgrav } 233b7579f77SDag-Erling Smørgrav 234b7579f77SDag-Erling Smørgrav int netblockstrtoaddr(const char* str, int port, struct sockaddr_storage* addr, 235b7579f77SDag-Erling Smørgrav socklen_t* addrlen, int* net) 236b7579f77SDag-Erling Smørgrav { 237b7579f77SDag-Erling Smørgrav char* s = NULL; 238b7579f77SDag-Erling Smørgrav *net = (str_is_ip6(str)?128:32); 239b7579f77SDag-Erling Smørgrav if((s=strchr(str, '/'))) { 240b7579f77SDag-Erling Smørgrav if(atoi(s+1) > *net) { 241b7579f77SDag-Erling Smørgrav log_err("netblock too large: %s", str); 242b7579f77SDag-Erling Smørgrav return 0; 243b7579f77SDag-Erling Smørgrav } 244b7579f77SDag-Erling Smørgrav *net = atoi(s+1); 245b7579f77SDag-Erling Smørgrav if(*net == 0 && strcmp(s+1, "0") != 0) { 246b7579f77SDag-Erling Smørgrav log_err("cannot parse netblock: '%s'", str); 247b7579f77SDag-Erling Smørgrav return 0; 248b7579f77SDag-Erling Smørgrav } 249b7579f77SDag-Erling Smørgrav if(!(s = strdup(str))) { 250b7579f77SDag-Erling Smørgrav log_err("out of memory"); 251b7579f77SDag-Erling Smørgrav return 0; 252b7579f77SDag-Erling Smørgrav } 253b7579f77SDag-Erling Smørgrav *strchr(s, '/') = '\0'; 254b7579f77SDag-Erling Smørgrav } 255b7579f77SDag-Erling Smørgrav if(!ipstrtoaddr(s?s:str, port, addr, addrlen)) { 256b7579f77SDag-Erling Smørgrav free(s); 257b7579f77SDag-Erling Smørgrav log_err("cannot parse ip address: '%s'", str); 258b7579f77SDag-Erling Smørgrav return 0; 259b7579f77SDag-Erling Smørgrav } 260b7579f77SDag-Erling Smørgrav if(s) { 261b7579f77SDag-Erling Smørgrav free(s); 262b7579f77SDag-Erling Smørgrav addr_mask(addr, *addrlen, *net); 263b7579f77SDag-Erling Smørgrav } 264b7579f77SDag-Erling Smørgrav return 1; 265b7579f77SDag-Erling Smørgrav } 266b7579f77SDag-Erling Smørgrav 267b7579f77SDag-Erling Smørgrav void 268b7579f77SDag-Erling Smørgrav log_nametypeclass(enum verbosity_value v, const char* str, uint8_t* name, 269b7579f77SDag-Erling Smørgrav uint16_t type, uint16_t dclass) 270b7579f77SDag-Erling Smørgrav { 271b7579f77SDag-Erling Smørgrav char buf[LDNS_MAX_DOMAINLEN+1]; 272b7579f77SDag-Erling Smørgrav char t[12], c[12]; 273b7579f77SDag-Erling Smørgrav const char *ts, *cs; 274b7579f77SDag-Erling Smørgrav if(verbosity < v) 275b7579f77SDag-Erling Smørgrav return; 276b7579f77SDag-Erling Smørgrav dname_str(name, buf); 277b7579f77SDag-Erling Smørgrav if(type == LDNS_RR_TYPE_TSIG) ts = "TSIG"; 278b7579f77SDag-Erling Smørgrav else if(type == LDNS_RR_TYPE_IXFR) ts = "IXFR"; 279b7579f77SDag-Erling Smørgrav else if(type == LDNS_RR_TYPE_AXFR) ts = "AXFR"; 280b7579f77SDag-Erling Smørgrav else if(type == LDNS_RR_TYPE_MAILB) ts = "MAILB"; 281b7579f77SDag-Erling Smørgrav else if(type == LDNS_RR_TYPE_MAILA) ts = "MAILA"; 282b7579f77SDag-Erling Smørgrav else if(type == LDNS_RR_TYPE_ANY) ts = "ANY"; 283b7579f77SDag-Erling Smørgrav else if(ldns_rr_descript(type) && ldns_rr_descript(type)->_name) 284b7579f77SDag-Erling Smørgrav ts = ldns_rr_descript(type)->_name; 285b7579f77SDag-Erling Smørgrav else { 286b7579f77SDag-Erling Smørgrav snprintf(t, sizeof(t), "TYPE%d", (int)type); 287b7579f77SDag-Erling Smørgrav ts = t; 288b7579f77SDag-Erling Smørgrav } 289b7579f77SDag-Erling Smørgrav if(ldns_lookup_by_id(ldns_rr_classes, (int)dclass) && 290b7579f77SDag-Erling Smørgrav ldns_lookup_by_id(ldns_rr_classes, (int)dclass)->name) 291b7579f77SDag-Erling Smørgrav cs = ldns_lookup_by_id(ldns_rr_classes, (int)dclass)->name; 292b7579f77SDag-Erling Smørgrav else { 293b7579f77SDag-Erling Smørgrav snprintf(c, sizeof(c), "CLASS%d", (int)dclass); 294b7579f77SDag-Erling Smørgrav cs = c; 295b7579f77SDag-Erling Smørgrav } 296b7579f77SDag-Erling Smørgrav log_info("%s %s %s %s", str, buf, ts, cs); 297b7579f77SDag-Erling Smørgrav } 298b7579f77SDag-Erling Smørgrav 299b7579f77SDag-Erling Smørgrav void log_name_addr(enum verbosity_value v, const char* str, uint8_t* zone, 300b7579f77SDag-Erling Smørgrav struct sockaddr_storage* addr, socklen_t addrlen) 301b7579f77SDag-Erling Smørgrav { 302b7579f77SDag-Erling Smørgrav uint16_t port; 303b7579f77SDag-Erling Smørgrav const char* family = "unknown_family "; 304b7579f77SDag-Erling Smørgrav char namebuf[LDNS_MAX_DOMAINLEN+1]; 305b7579f77SDag-Erling Smørgrav char dest[100]; 306b7579f77SDag-Erling Smørgrav int af = (int)((struct sockaddr_in*)addr)->sin_family; 307b7579f77SDag-Erling Smørgrav void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr; 308b7579f77SDag-Erling Smørgrav if(verbosity < v) 309b7579f77SDag-Erling Smørgrav return; 310b7579f77SDag-Erling Smørgrav switch(af) { 311b7579f77SDag-Erling Smørgrav case AF_INET: family=""; break; 312b7579f77SDag-Erling Smørgrav case AF_INET6: family=""; 313b7579f77SDag-Erling Smørgrav sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr; 314b7579f77SDag-Erling Smørgrav break; 315b7579f77SDag-Erling Smørgrav case AF_UNIX: family="unix_family "; break; 316b7579f77SDag-Erling Smørgrav default: break; 317b7579f77SDag-Erling Smørgrav } 318b7579f77SDag-Erling Smørgrav if(inet_ntop(af, sinaddr, dest, (socklen_t)sizeof(dest)) == 0) { 319b7579f77SDag-Erling Smørgrav strncpy(dest, "(inet_ntop error)", sizeof(dest)); 320b7579f77SDag-Erling Smørgrav } 321b7579f77SDag-Erling Smørgrav dest[sizeof(dest)-1] = 0; 322b7579f77SDag-Erling Smørgrav port = ntohs(((struct sockaddr_in*)addr)->sin_port); 323b7579f77SDag-Erling Smørgrav dname_str(zone, namebuf); 324b7579f77SDag-Erling Smørgrav if(af != AF_INET && af != AF_INET6) 325b7579f77SDag-Erling Smørgrav verbose(v, "%s <%s> %s%s#%d (addrlen %d)", 326b7579f77SDag-Erling Smørgrav str, namebuf, family, dest, (int)port, (int)addrlen); 327b7579f77SDag-Erling Smørgrav else verbose(v, "%s <%s> %s%s#%d", 328b7579f77SDag-Erling Smørgrav str, namebuf, family, dest, (int)port); 329b7579f77SDag-Erling Smørgrav } 330b7579f77SDag-Erling Smørgrav 331b7579f77SDag-Erling Smørgrav int 332b7579f77SDag-Erling Smørgrav sockaddr_cmp(struct sockaddr_storage* addr1, socklen_t len1, 333b7579f77SDag-Erling Smørgrav struct sockaddr_storage* addr2, socklen_t len2) 334b7579f77SDag-Erling Smørgrav { 335b7579f77SDag-Erling Smørgrav struct sockaddr_in* p1_in = (struct sockaddr_in*)addr1; 336b7579f77SDag-Erling Smørgrav struct sockaddr_in* p2_in = (struct sockaddr_in*)addr2; 337b7579f77SDag-Erling Smørgrav struct sockaddr_in6* p1_in6 = (struct sockaddr_in6*)addr1; 338b7579f77SDag-Erling Smørgrav struct sockaddr_in6* p2_in6 = (struct sockaddr_in6*)addr2; 339b7579f77SDag-Erling Smørgrav if(len1 < len2) 340b7579f77SDag-Erling Smørgrav return -1; 341b7579f77SDag-Erling Smørgrav if(len1 > len2) 342b7579f77SDag-Erling Smørgrav return 1; 343b7579f77SDag-Erling Smørgrav log_assert(len1 == len2); 344b7579f77SDag-Erling Smørgrav if( p1_in->sin_family < p2_in->sin_family) 345b7579f77SDag-Erling Smørgrav return -1; 346b7579f77SDag-Erling Smørgrav if( p1_in->sin_family > p2_in->sin_family) 347b7579f77SDag-Erling Smørgrav return 1; 348b7579f77SDag-Erling Smørgrav log_assert( p1_in->sin_family == p2_in->sin_family ); 349b7579f77SDag-Erling Smørgrav /* compare ip4 */ 350b7579f77SDag-Erling Smørgrav if( p1_in->sin_family == AF_INET ) { 351b7579f77SDag-Erling Smørgrav /* just order it, ntohs not required */ 352b7579f77SDag-Erling Smørgrav if(p1_in->sin_port < p2_in->sin_port) 353b7579f77SDag-Erling Smørgrav return -1; 354b7579f77SDag-Erling Smørgrav if(p1_in->sin_port > p2_in->sin_port) 355b7579f77SDag-Erling Smørgrav return 1; 356b7579f77SDag-Erling Smørgrav log_assert(p1_in->sin_port == p2_in->sin_port); 357b7579f77SDag-Erling Smørgrav return memcmp(&p1_in->sin_addr, &p2_in->sin_addr, INET_SIZE); 358b7579f77SDag-Erling Smørgrav } else if (p1_in6->sin6_family == AF_INET6) { 359b7579f77SDag-Erling Smørgrav /* just order it, ntohs not required */ 360b7579f77SDag-Erling Smørgrav if(p1_in6->sin6_port < p2_in6->sin6_port) 361b7579f77SDag-Erling Smørgrav return -1; 362b7579f77SDag-Erling Smørgrav if(p1_in6->sin6_port > p2_in6->sin6_port) 363b7579f77SDag-Erling Smørgrav return 1; 364b7579f77SDag-Erling Smørgrav log_assert(p1_in6->sin6_port == p2_in6->sin6_port); 365b7579f77SDag-Erling Smørgrav return memcmp(&p1_in6->sin6_addr, &p2_in6->sin6_addr, 366b7579f77SDag-Erling Smørgrav INET6_SIZE); 367b7579f77SDag-Erling Smørgrav } else { 368b7579f77SDag-Erling Smørgrav /* eek unknown type, perform this comparison for sanity. */ 369b7579f77SDag-Erling Smørgrav return memcmp(addr1, addr2, len1); 370b7579f77SDag-Erling Smørgrav } 371b7579f77SDag-Erling Smørgrav } 372b7579f77SDag-Erling Smørgrav 373b7579f77SDag-Erling Smørgrav int 374b7579f77SDag-Erling Smørgrav sockaddr_cmp_addr(struct sockaddr_storage* addr1, socklen_t len1, 375b7579f77SDag-Erling Smørgrav struct sockaddr_storage* addr2, socklen_t len2) 376b7579f77SDag-Erling Smørgrav { 377b7579f77SDag-Erling Smørgrav struct sockaddr_in* p1_in = (struct sockaddr_in*)addr1; 378b7579f77SDag-Erling Smørgrav struct sockaddr_in* p2_in = (struct sockaddr_in*)addr2; 379b7579f77SDag-Erling Smørgrav struct sockaddr_in6* p1_in6 = (struct sockaddr_in6*)addr1; 380b7579f77SDag-Erling Smørgrav struct sockaddr_in6* p2_in6 = (struct sockaddr_in6*)addr2; 381b7579f77SDag-Erling Smørgrav if(len1 < len2) 382b7579f77SDag-Erling Smørgrav return -1; 383b7579f77SDag-Erling Smørgrav if(len1 > len2) 384b7579f77SDag-Erling Smørgrav return 1; 385b7579f77SDag-Erling Smørgrav log_assert(len1 == len2); 386b7579f77SDag-Erling Smørgrav if( p1_in->sin_family < p2_in->sin_family) 387b7579f77SDag-Erling Smørgrav return -1; 388b7579f77SDag-Erling Smørgrav if( p1_in->sin_family > p2_in->sin_family) 389b7579f77SDag-Erling Smørgrav return 1; 390b7579f77SDag-Erling Smørgrav log_assert( p1_in->sin_family == p2_in->sin_family ); 391b7579f77SDag-Erling Smørgrav /* compare ip4 */ 392b7579f77SDag-Erling Smørgrav if( p1_in->sin_family == AF_INET ) { 393b7579f77SDag-Erling Smørgrav return memcmp(&p1_in->sin_addr, &p2_in->sin_addr, INET_SIZE); 394b7579f77SDag-Erling Smørgrav } else if (p1_in6->sin6_family == AF_INET6) { 395b7579f77SDag-Erling Smørgrav return memcmp(&p1_in6->sin6_addr, &p2_in6->sin6_addr, 396b7579f77SDag-Erling Smørgrav INET6_SIZE); 397b7579f77SDag-Erling Smørgrav } else { 398b7579f77SDag-Erling Smørgrav /* eek unknown type, perform this comparison for sanity. */ 399b7579f77SDag-Erling Smørgrav return memcmp(addr1, addr2, len1); 400b7579f77SDag-Erling Smørgrav } 401b7579f77SDag-Erling Smørgrav } 402b7579f77SDag-Erling Smørgrav 403b7579f77SDag-Erling Smørgrav int 404b7579f77SDag-Erling Smørgrav addr_is_ip6(struct sockaddr_storage* addr, socklen_t len) 405b7579f77SDag-Erling Smørgrav { 406b7579f77SDag-Erling Smørgrav if(len == (socklen_t)sizeof(struct sockaddr_in6) && 407b7579f77SDag-Erling Smørgrav ((struct sockaddr_in6*)addr)->sin6_family == AF_INET6) 408b7579f77SDag-Erling Smørgrav return 1; 409b7579f77SDag-Erling Smørgrav else return 0; 410b7579f77SDag-Erling Smørgrav } 411b7579f77SDag-Erling Smørgrav 412b7579f77SDag-Erling Smørgrav void 413b7579f77SDag-Erling Smørgrav addr_mask(struct sockaddr_storage* addr, socklen_t len, int net) 414b7579f77SDag-Erling Smørgrav { 415b7579f77SDag-Erling Smørgrav uint8_t mask[8] = {0x0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe}; 416b7579f77SDag-Erling Smørgrav int i, max; 417b7579f77SDag-Erling Smørgrav uint8_t* s; 418b7579f77SDag-Erling Smørgrav if(addr_is_ip6(addr, len)) { 419b7579f77SDag-Erling Smørgrav s = (uint8_t*)&((struct sockaddr_in6*)addr)->sin6_addr; 420b7579f77SDag-Erling Smørgrav max = 128; 421b7579f77SDag-Erling Smørgrav } else { 422b7579f77SDag-Erling Smørgrav s = (uint8_t*)&((struct sockaddr_in*)addr)->sin_addr; 423b7579f77SDag-Erling Smørgrav max = 32; 424b7579f77SDag-Erling Smørgrav } 425b7579f77SDag-Erling Smørgrav if(net >= max) 426b7579f77SDag-Erling Smørgrav return; 427b7579f77SDag-Erling Smørgrav for(i=net/8+1; i<max/8; i++) { 428b7579f77SDag-Erling Smørgrav s[i] = 0; 429b7579f77SDag-Erling Smørgrav } 430b7579f77SDag-Erling Smørgrav s[net/8] &= mask[net&0x7]; 431b7579f77SDag-Erling Smørgrav } 432b7579f77SDag-Erling Smørgrav 433b7579f77SDag-Erling Smørgrav int 434b7579f77SDag-Erling Smørgrav addr_in_common(struct sockaddr_storage* addr1, int net1, 435b7579f77SDag-Erling Smørgrav struct sockaddr_storage* addr2, int net2, socklen_t addrlen) 436b7579f77SDag-Erling Smørgrav { 437b7579f77SDag-Erling Smørgrav int min = (net1<net2)?net1:net2; 438b7579f77SDag-Erling Smørgrav int i, to; 439b7579f77SDag-Erling Smørgrav int match = 0; 440b7579f77SDag-Erling Smørgrav uint8_t* s1, *s2; 441b7579f77SDag-Erling Smørgrav if(addr_is_ip6(addr1, addrlen)) { 442b7579f77SDag-Erling Smørgrav s1 = (uint8_t*)&((struct sockaddr_in6*)addr1)->sin6_addr; 443b7579f77SDag-Erling Smørgrav s2 = (uint8_t*)&((struct sockaddr_in6*)addr2)->sin6_addr; 444b7579f77SDag-Erling Smørgrav to = 16; 445b7579f77SDag-Erling Smørgrav } else { 446b7579f77SDag-Erling Smørgrav s1 = (uint8_t*)&((struct sockaddr_in*)addr1)->sin_addr; 447b7579f77SDag-Erling Smørgrav s2 = (uint8_t*)&((struct sockaddr_in*)addr2)->sin_addr; 448b7579f77SDag-Erling Smørgrav to = 4; 449b7579f77SDag-Erling Smørgrav } 450b7579f77SDag-Erling Smørgrav /* match = bits_in_common(s1, s2, to); */ 451b7579f77SDag-Erling Smørgrav for(i=0; i<to; i++) { 452b7579f77SDag-Erling Smørgrav if(s1[i] == s2[i]) { 453b7579f77SDag-Erling Smørgrav match += 8; 454b7579f77SDag-Erling Smørgrav } else { 455b7579f77SDag-Erling Smørgrav uint8_t z = s1[i]^s2[i]; 456b7579f77SDag-Erling Smørgrav log_assert(z); 457b7579f77SDag-Erling Smørgrav while(!(z&0x80)) { 458b7579f77SDag-Erling Smørgrav match++; 459b7579f77SDag-Erling Smørgrav z<<=1; 460b7579f77SDag-Erling Smørgrav } 461b7579f77SDag-Erling Smørgrav break; 462b7579f77SDag-Erling Smørgrav } 463b7579f77SDag-Erling Smørgrav } 464b7579f77SDag-Erling Smørgrav if(match > min) match = min; 465b7579f77SDag-Erling Smørgrav return match; 466b7579f77SDag-Erling Smørgrav } 467b7579f77SDag-Erling Smørgrav 468b7579f77SDag-Erling Smørgrav void 469b7579f77SDag-Erling Smørgrav addr_to_str(struct sockaddr_storage* addr, socklen_t addrlen, 470b7579f77SDag-Erling Smørgrav char* buf, size_t len) 471b7579f77SDag-Erling Smørgrav { 472b7579f77SDag-Erling Smørgrav int af = (int)((struct sockaddr_in*)addr)->sin_family; 473b7579f77SDag-Erling Smørgrav void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr; 474b7579f77SDag-Erling Smørgrav if(addr_is_ip6(addr, addrlen)) 475b7579f77SDag-Erling Smørgrav sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr; 476b7579f77SDag-Erling Smørgrav if(inet_ntop(af, sinaddr, buf, (socklen_t)len) == 0) { 477b7579f77SDag-Erling Smørgrav snprintf(buf, len, "(inet_ntop_error)"); 478b7579f77SDag-Erling Smørgrav } 479b7579f77SDag-Erling Smørgrav } 480b7579f77SDag-Erling Smørgrav 481b7579f77SDag-Erling Smørgrav int 482b7579f77SDag-Erling Smørgrav addr_is_ip4mapped(struct sockaddr_storage* addr, socklen_t addrlen) 483b7579f77SDag-Erling Smørgrav { 484b7579f77SDag-Erling Smørgrav /* prefix for ipv4 into ipv6 mapping is ::ffff:x.x.x.x */ 485b7579f77SDag-Erling Smørgrav const uint8_t map_prefix[16] = 486b7579f77SDag-Erling Smørgrav {0,0,0,0, 0,0,0,0, 0,0,0xff,0xff, 0,0,0,0}; 487b7579f77SDag-Erling Smørgrav uint8_t* s; 488b7579f77SDag-Erling Smørgrav if(!addr_is_ip6(addr, addrlen)) 489b7579f77SDag-Erling Smørgrav return 0; 490b7579f77SDag-Erling Smørgrav /* s is 16 octet ipv6 address string */ 491b7579f77SDag-Erling Smørgrav s = (uint8_t*)&((struct sockaddr_in6*)addr)->sin6_addr; 492b7579f77SDag-Erling Smørgrav return (memcmp(s, map_prefix, 12) == 0); 493b7579f77SDag-Erling Smørgrav } 494b7579f77SDag-Erling Smørgrav 495b7579f77SDag-Erling Smørgrav int addr_is_broadcast(struct sockaddr_storage* addr, socklen_t addrlen) 496b7579f77SDag-Erling Smørgrav { 497b7579f77SDag-Erling Smørgrav int af = (int)((struct sockaddr_in*)addr)->sin_family; 498b7579f77SDag-Erling Smørgrav void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr; 499b7579f77SDag-Erling Smørgrav return af == AF_INET && addrlen>=(socklen_t)sizeof(struct sockaddr_in) 500b7579f77SDag-Erling Smørgrav && memcmp(sinaddr, "\377\377\377\377", 4) == 0; 501b7579f77SDag-Erling Smørgrav } 502b7579f77SDag-Erling Smørgrav 503b7579f77SDag-Erling Smørgrav int addr_is_any(struct sockaddr_storage* addr, socklen_t addrlen) 504b7579f77SDag-Erling Smørgrav { 505b7579f77SDag-Erling Smørgrav int af = (int)((struct sockaddr_in*)addr)->sin_family; 506b7579f77SDag-Erling Smørgrav void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr; 507b7579f77SDag-Erling Smørgrav void* sin6addr = &((struct sockaddr_in6*)addr)->sin6_addr; 508b7579f77SDag-Erling Smørgrav if(af == AF_INET && addrlen>=(socklen_t)sizeof(struct sockaddr_in) 509b7579f77SDag-Erling Smørgrav && memcmp(sinaddr, "\000\000\000\000", 4) == 0) 510b7579f77SDag-Erling Smørgrav return 1; 511b7579f77SDag-Erling Smørgrav else if(af==AF_INET6 && addrlen>=(socklen_t)sizeof(struct sockaddr_in6) 512b7579f77SDag-Erling Smørgrav && memcmp(sin6addr, "\000\000\000\000\000\000\000\000" 513b7579f77SDag-Erling Smørgrav "\000\000\000\000\000\000\000\000", 16) == 0) 514b7579f77SDag-Erling Smørgrav return 1; 515b7579f77SDag-Erling Smørgrav return 0; 516b7579f77SDag-Erling Smørgrav } 517b7579f77SDag-Erling Smørgrav 518b7579f77SDag-Erling Smørgrav void sock_list_insert(struct sock_list** list, struct sockaddr_storage* addr, 519b7579f77SDag-Erling Smørgrav socklen_t len, struct regional* region) 520b7579f77SDag-Erling Smørgrav { 521b7579f77SDag-Erling Smørgrav struct sock_list* add = (struct sock_list*)regional_alloc(region, 522b7579f77SDag-Erling Smørgrav sizeof(*add) - sizeof(add->addr) + (size_t)len); 523b7579f77SDag-Erling Smørgrav if(!add) { 524b7579f77SDag-Erling Smørgrav log_err("out of memory in socketlist insert"); 525b7579f77SDag-Erling Smørgrav return; 526b7579f77SDag-Erling Smørgrav } 527b7579f77SDag-Erling Smørgrav log_assert(list); 528b7579f77SDag-Erling Smørgrav add->next = *list; 529b7579f77SDag-Erling Smørgrav add->len = len; 530b7579f77SDag-Erling Smørgrav *list = add; 531b7579f77SDag-Erling Smørgrav if(len) memmove(&add->addr, addr, len); 532b7579f77SDag-Erling Smørgrav } 533b7579f77SDag-Erling Smørgrav 534b7579f77SDag-Erling Smørgrav void sock_list_prepend(struct sock_list** list, struct sock_list* add) 535b7579f77SDag-Erling Smørgrav { 536b7579f77SDag-Erling Smørgrav struct sock_list* last = add; 537b7579f77SDag-Erling Smørgrav if(!last) 538b7579f77SDag-Erling Smørgrav return; 539b7579f77SDag-Erling Smørgrav while(last->next) 540b7579f77SDag-Erling Smørgrav last = last->next; 541b7579f77SDag-Erling Smørgrav last->next = *list; 542b7579f77SDag-Erling Smørgrav *list = add; 543b7579f77SDag-Erling Smørgrav } 544b7579f77SDag-Erling Smørgrav 545b7579f77SDag-Erling Smørgrav int sock_list_find(struct sock_list* list, struct sockaddr_storage* addr, 546b7579f77SDag-Erling Smørgrav socklen_t len) 547b7579f77SDag-Erling Smørgrav { 548b7579f77SDag-Erling Smørgrav while(list) { 549b7579f77SDag-Erling Smørgrav if(len == list->len) { 550b7579f77SDag-Erling Smørgrav if(len == 0 || sockaddr_cmp_addr(addr, len, 551b7579f77SDag-Erling Smørgrav &list->addr, list->len) == 0) 552b7579f77SDag-Erling Smørgrav return 1; 553b7579f77SDag-Erling Smørgrav } 554b7579f77SDag-Erling Smørgrav list = list->next; 555b7579f77SDag-Erling Smørgrav } 556b7579f77SDag-Erling Smørgrav return 0; 557b7579f77SDag-Erling Smørgrav } 558b7579f77SDag-Erling Smørgrav 559b7579f77SDag-Erling Smørgrav void sock_list_merge(struct sock_list** list, struct regional* region, 560b7579f77SDag-Erling Smørgrav struct sock_list* add) 561b7579f77SDag-Erling Smørgrav { 562b7579f77SDag-Erling Smørgrav struct sock_list* p; 563b7579f77SDag-Erling Smørgrav for(p=add; p; p=p->next) { 564b7579f77SDag-Erling Smørgrav if(!sock_list_find(*list, &p->addr, p->len)) 565b7579f77SDag-Erling Smørgrav sock_list_insert(list, &p->addr, p->len, region); 566b7579f77SDag-Erling Smørgrav } 567b7579f77SDag-Erling Smørgrav } 568b7579f77SDag-Erling Smørgrav 569b7579f77SDag-Erling Smørgrav void 570b7579f77SDag-Erling Smørgrav log_crypto_err(const char* str) 571b7579f77SDag-Erling Smørgrav { 572*8ed2b524SDag-Erling Smørgrav #ifdef HAVE_SSL 573b7579f77SDag-Erling Smørgrav /* error:[error code]:[library name]:[function name]:[reason string] */ 574b7579f77SDag-Erling Smørgrav char buf[128]; 575b7579f77SDag-Erling Smørgrav unsigned long e; 576b7579f77SDag-Erling Smørgrav ERR_error_string_n(ERR_get_error(), buf, sizeof(buf)); 577b7579f77SDag-Erling Smørgrav log_err("%s crypto %s", str, buf); 578b7579f77SDag-Erling Smørgrav while( (e=ERR_get_error()) ) { 579b7579f77SDag-Erling Smørgrav ERR_error_string_n(e, buf, sizeof(buf)); 580b7579f77SDag-Erling Smørgrav log_err("and additionally crypto %s", buf); 581b7579f77SDag-Erling Smørgrav } 582*8ed2b524SDag-Erling Smørgrav #else 583*8ed2b524SDag-Erling Smørgrav (void)str; 584*8ed2b524SDag-Erling Smørgrav #endif /* HAVE_SSL */ 585b7579f77SDag-Erling Smørgrav } 586b7579f77SDag-Erling Smørgrav 587b7579f77SDag-Erling Smørgrav void* listen_sslctx_create(char* key, char* pem, char* verifypem) 588b7579f77SDag-Erling Smørgrav { 589*8ed2b524SDag-Erling Smørgrav #ifdef HAVE_SSL 590b7579f77SDag-Erling Smørgrav SSL_CTX* ctx = SSL_CTX_new(SSLv23_server_method()); 591b7579f77SDag-Erling Smørgrav if(!ctx) { 592b7579f77SDag-Erling Smørgrav log_crypto_err("could not SSL_CTX_new"); 593b7579f77SDag-Erling Smørgrav return NULL; 594b7579f77SDag-Erling Smørgrav } 595b7579f77SDag-Erling Smørgrav /* no SSLv2 because has defects */ 596b7579f77SDag-Erling Smørgrav if(!(SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2)){ 597b7579f77SDag-Erling Smørgrav log_crypto_err("could not set SSL_OP_NO_SSLv2"); 598b7579f77SDag-Erling Smørgrav SSL_CTX_free(ctx); 599b7579f77SDag-Erling Smørgrav return NULL; 600b7579f77SDag-Erling Smørgrav } 601b7579f77SDag-Erling Smørgrav if(!SSL_CTX_use_certificate_file(ctx, pem, SSL_FILETYPE_PEM)) { 602b7579f77SDag-Erling Smørgrav log_err("error for cert file: %s", pem); 603b7579f77SDag-Erling Smørgrav log_crypto_err("error in SSL_CTX use_certificate_file"); 604b7579f77SDag-Erling Smørgrav SSL_CTX_free(ctx); 605b7579f77SDag-Erling Smørgrav return NULL; 606b7579f77SDag-Erling Smørgrav } 607b7579f77SDag-Erling Smørgrav if(!SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM)) { 608b7579f77SDag-Erling Smørgrav log_err("error for private key file: %s", key); 609b7579f77SDag-Erling Smørgrav log_crypto_err("Error in SSL_CTX use_PrivateKey_file"); 610b7579f77SDag-Erling Smørgrav SSL_CTX_free(ctx); 611b7579f77SDag-Erling Smørgrav return NULL; 612b7579f77SDag-Erling Smørgrav } 613b7579f77SDag-Erling Smørgrav if(!SSL_CTX_check_private_key(ctx)) { 614b7579f77SDag-Erling Smørgrav log_err("error for key file: %s", key); 615b7579f77SDag-Erling Smørgrav log_crypto_err("Error in SSL_CTX check_private_key"); 616b7579f77SDag-Erling Smørgrav SSL_CTX_free(ctx); 617b7579f77SDag-Erling Smørgrav return NULL; 618b7579f77SDag-Erling Smørgrav } 619b7579f77SDag-Erling Smørgrav 620b7579f77SDag-Erling Smørgrav if(verifypem && verifypem[0]) { 621b7579f77SDag-Erling Smørgrav if(!SSL_CTX_load_verify_locations(ctx, verifypem, NULL)) { 622b7579f77SDag-Erling Smørgrav log_crypto_err("Error in SSL_CTX verify locations"); 623b7579f77SDag-Erling Smørgrav SSL_CTX_free(ctx); 624b7579f77SDag-Erling Smørgrav return NULL; 625b7579f77SDag-Erling Smørgrav } 626b7579f77SDag-Erling Smørgrav SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file( 627b7579f77SDag-Erling Smørgrav verifypem)); 628b7579f77SDag-Erling Smørgrav SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); 629b7579f77SDag-Erling Smørgrav } 630b7579f77SDag-Erling Smørgrav return ctx; 631*8ed2b524SDag-Erling Smørgrav #else 632*8ed2b524SDag-Erling Smørgrav (void)key; (void)pem; (void)verifypem; 633*8ed2b524SDag-Erling Smørgrav return NULL; 634*8ed2b524SDag-Erling Smørgrav #endif 635b7579f77SDag-Erling Smørgrav } 636b7579f77SDag-Erling Smørgrav 637b7579f77SDag-Erling Smørgrav void* connect_sslctx_create(char* key, char* pem, char* verifypem) 638b7579f77SDag-Erling Smørgrav { 639*8ed2b524SDag-Erling Smørgrav #ifdef HAVE_SSL 640b7579f77SDag-Erling Smørgrav SSL_CTX* ctx = SSL_CTX_new(SSLv23_client_method()); 641b7579f77SDag-Erling Smørgrav if(!ctx) { 642b7579f77SDag-Erling Smørgrav log_crypto_err("could not allocate SSL_CTX pointer"); 643b7579f77SDag-Erling Smørgrav return NULL; 644b7579f77SDag-Erling Smørgrav } 645b7579f77SDag-Erling Smørgrav if(!(SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2)) { 646b7579f77SDag-Erling Smørgrav log_crypto_err("could not set SSL_OP_NO_SSLv2"); 647b7579f77SDag-Erling Smørgrav SSL_CTX_free(ctx); 648b7579f77SDag-Erling Smørgrav return NULL; 649b7579f77SDag-Erling Smørgrav } 650b7579f77SDag-Erling Smørgrav if(key && key[0]) { 651b7579f77SDag-Erling Smørgrav if(!SSL_CTX_use_certificate_file(ctx, pem, SSL_FILETYPE_PEM)) { 652b7579f77SDag-Erling Smørgrav log_err("error in client certificate %s", pem); 653b7579f77SDag-Erling Smørgrav log_crypto_err("error in certificate file"); 654b7579f77SDag-Erling Smørgrav SSL_CTX_free(ctx); 655b7579f77SDag-Erling Smørgrav return NULL; 656b7579f77SDag-Erling Smørgrav } 657b7579f77SDag-Erling Smørgrav if(!SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM)) { 658b7579f77SDag-Erling Smørgrav log_err("error in client private key %s", key); 659b7579f77SDag-Erling Smørgrav log_crypto_err("error in key file"); 660b7579f77SDag-Erling Smørgrav SSL_CTX_free(ctx); 661b7579f77SDag-Erling Smørgrav return NULL; 662b7579f77SDag-Erling Smørgrav } 663b7579f77SDag-Erling Smørgrav if(!SSL_CTX_check_private_key(ctx)) { 664b7579f77SDag-Erling Smørgrav log_err("error in client key %s", key); 665b7579f77SDag-Erling Smørgrav log_crypto_err("error in SSL_CTX_check_private_key"); 666b7579f77SDag-Erling Smørgrav SSL_CTX_free(ctx); 667b7579f77SDag-Erling Smørgrav return NULL; 668b7579f77SDag-Erling Smørgrav } 669b7579f77SDag-Erling Smørgrav } 670b7579f77SDag-Erling Smørgrav if(verifypem && verifypem[0]) { 671b7579f77SDag-Erling Smørgrav if(!SSL_CTX_load_verify_locations(ctx, verifypem, NULL) != 1) { 672b7579f77SDag-Erling Smørgrav log_crypto_err("error in SSL_CTX verify"); 673b7579f77SDag-Erling Smørgrav SSL_CTX_free(ctx); 674b7579f77SDag-Erling Smørgrav return NULL; 675b7579f77SDag-Erling Smørgrav } 676b7579f77SDag-Erling Smørgrav SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); 677b7579f77SDag-Erling Smørgrav } 678b7579f77SDag-Erling Smørgrav return ctx; 679*8ed2b524SDag-Erling Smørgrav #else 680*8ed2b524SDag-Erling Smørgrav (void)key; (void)pem; (void)verifypem; 681*8ed2b524SDag-Erling Smørgrav return NULL; 682*8ed2b524SDag-Erling Smørgrav #endif 683b7579f77SDag-Erling Smørgrav } 684b7579f77SDag-Erling Smørgrav 685b7579f77SDag-Erling Smørgrav void* incoming_ssl_fd(void* sslctx, int fd) 686b7579f77SDag-Erling Smørgrav { 687*8ed2b524SDag-Erling Smørgrav #ifdef HAVE_SSL 688b7579f77SDag-Erling Smørgrav SSL* ssl = SSL_new((SSL_CTX*)sslctx); 689b7579f77SDag-Erling Smørgrav if(!ssl) { 690b7579f77SDag-Erling Smørgrav log_crypto_err("could not SSL_new"); 691b7579f77SDag-Erling Smørgrav return NULL; 692b7579f77SDag-Erling Smørgrav } 693b7579f77SDag-Erling Smørgrav SSL_set_accept_state(ssl); 694b7579f77SDag-Erling Smørgrav (void)SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); 695b7579f77SDag-Erling Smørgrav if(!SSL_set_fd(ssl, fd)) { 696b7579f77SDag-Erling Smørgrav log_crypto_err("could not SSL_set_fd"); 697b7579f77SDag-Erling Smørgrav SSL_free(ssl); 698b7579f77SDag-Erling Smørgrav return NULL; 699b7579f77SDag-Erling Smørgrav } 700b7579f77SDag-Erling Smørgrav return ssl; 701*8ed2b524SDag-Erling Smørgrav #else 702*8ed2b524SDag-Erling Smørgrav (void)sslctx; (void)fd; 703*8ed2b524SDag-Erling Smørgrav return NULL; 704*8ed2b524SDag-Erling Smørgrav #endif 705b7579f77SDag-Erling Smørgrav } 706b7579f77SDag-Erling Smørgrav 707b7579f77SDag-Erling Smørgrav void* outgoing_ssl_fd(void* sslctx, int fd) 708b7579f77SDag-Erling Smørgrav { 709*8ed2b524SDag-Erling Smørgrav #ifdef HAVE_SSL 710b7579f77SDag-Erling Smørgrav SSL* ssl = SSL_new((SSL_CTX*)sslctx); 711b7579f77SDag-Erling Smørgrav if(!ssl) { 712b7579f77SDag-Erling Smørgrav log_crypto_err("could not SSL_new"); 713b7579f77SDag-Erling Smørgrav return NULL; 714b7579f77SDag-Erling Smørgrav } 715b7579f77SDag-Erling Smørgrav SSL_set_connect_state(ssl); 716b7579f77SDag-Erling Smørgrav (void)SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); 717b7579f77SDag-Erling Smørgrav if(!SSL_set_fd(ssl, fd)) { 718b7579f77SDag-Erling Smørgrav log_crypto_err("could not SSL_set_fd"); 719b7579f77SDag-Erling Smørgrav SSL_free(ssl); 720b7579f77SDag-Erling Smørgrav return NULL; 721b7579f77SDag-Erling Smørgrav } 722b7579f77SDag-Erling Smørgrav return ssl; 723*8ed2b524SDag-Erling Smørgrav #else 724*8ed2b524SDag-Erling Smørgrav (void)sslctx; (void)fd; 725*8ed2b524SDag-Erling Smørgrav return NULL; 726*8ed2b524SDag-Erling Smørgrav #endif 727b7579f77SDag-Erling Smørgrav } 728*8ed2b524SDag-Erling Smørgrav 729*8ed2b524SDag-Erling Smørgrav #if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) 730*8ed2b524SDag-Erling Smørgrav /** global lock list for openssl locks */ 731*8ed2b524SDag-Erling Smørgrav static lock_basic_t *ub_openssl_locks = NULL; 732*8ed2b524SDag-Erling Smørgrav 733*8ed2b524SDag-Erling Smørgrav /** callback that gets thread id for openssl */ 734*8ed2b524SDag-Erling Smørgrav static unsigned long 735*8ed2b524SDag-Erling Smørgrav ub_crypto_id_cb(void) 736*8ed2b524SDag-Erling Smørgrav { 737*8ed2b524SDag-Erling Smørgrav return (unsigned long)ub_thread_self(); 738*8ed2b524SDag-Erling Smørgrav } 739*8ed2b524SDag-Erling Smørgrav 740*8ed2b524SDag-Erling Smørgrav static void 741*8ed2b524SDag-Erling Smørgrav ub_crypto_lock_cb(int mode, int type, const char *ATTR_UNUSED(file), 742*8ed2b524SDag-Erling Smørgrav int ATTR_UNUSED(line)) 743*8ed2b524SDag-Erling Smørgrav { 744*8ed2b524SDag-Erling Smørgrav if((mode&CRYPTO_LOCK)) { 745*8ed2b524SDag-Erling Smørgrav lock_basic_lock(&ub_openssl_locks[type]); 746*8ed2b524SDag-Erling Smørgrav } else { 747*8ed2b524SDag-Erling Smørgrav lock_basic_unlock(&ub_openssl_locks[type]); 748*8ed2b524SDag-Erling Smørgrav } 749*8ed2b524SDag-Erling Smørgrav } 750*8ed2b524SDag-Erling Smørgrav #endif /* OPENSSL_THREADS */ 751*8ed2b524SDag-Erling Smørgrav 752*8ed2b524SDag-Erling Smørgrav int ub_openssl_lock_init(void) 753*8ed2b524SDag-Erling Smørgrav { 754*8ed2b524SDag-Erling Smørgrav #if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) 755*8ed2b524SDag-Erling Smørgrav int i; 756*8ed2b524SDag-Erling Smørgrav ub_openssl_locks = (lock_basic_t*)malloc( 757*8ed2b524SDag-Erling Smørgrav sizeof(lock_basic_t)*CRYPTO_num_locks()); 758*8ed2b524SDag-Erling Smørgrav if(!ub_openssl_locks) 759*8ed2b524SDag-Erling Smørgrav return 0; 760*8ed2b524SDag-Erling Smørgrav for(i=0; i<CRYPTO_num_locks(); i++) { 761*8ed2b524SDag-Erling Smørgrav lock_basic_init(&ub_openssl_locks[i]); 762*8ed2b524SDag-Erling Smørgrav } 763*8ed2b524SDag-Erling Smørgrav CRYPTO_set_id_callback(&ub_crypto_id_cb); 764*8ed2b524SDag-Erling Smørgrav CRYPTO_set_locking_callback(&ub_crypto_lock_cb); 765*8ed2b524SDag-Erling Smørgrav #endif /* OPENSSL_THREADS */ 766*8ed2b524SDag-Erling Smørgrav return 1; 767*8ed2b524SDag-Erling Smørgrav } 768*8ed2b524SDag-Erling Smørgrav 769*8ed2b524SDag-Erling Smørgrav void ub_openssl_lock_delete(void) 770*8ed2b524SDag-Erling Smørgrav { 771*8ed2b524SDag-Erling Smørgrav #if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) 772*8ed2b524SDag-Erling Smørgrav int i; 773*8ed2b524SDag-Erling Smørgrav if(!ub_openssl_locks) 774*8ed2b524SDag-Erling Smørgrav return; 775*8ed2b524SDag-Erling Smørgrav CRYPTO_set_id_callback(NULL); 776*8ed2b524SDag-Erling Smørgrav CRYPTO_set_locking_callback(NULL); 777*8ed2b524SDag-Erling Smørgrav for(i=0; i<CRYPTO_num_locks(); i++) { 778*8ed2b524SDag-Erling Smørgrav lock_basic_destroy(&ub_openssl_locks[i]); 779*8ed2b524SDag-Erling Smørgrav } 780*8ed2b524SDag-Erling Smørgrav free(ub_openssl_locks); 781*8ed2b524SDag-Erling Smørgrav #endif /* OPENSSL_THREADS */ 782*8ed2b524SDag-Erling Smørgrav } 783*8ed2b524SDag-Erling Smørgrav 784