1 /* $NetBSD: feature-test.c,v 1.13 2025/01/26 16:24:35 christos Exp $ */ 2 3 /* 4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 * 6 * SPDX-License-Identifier: MPL-2.0 7 * 8 * This Source Code Form is subject to the terms of the Mozilla Public 9 * License, v. 2.0. If a copy of the MPL was not distributed with this 10 * file, you can obtain one at https://mozilla.org/MPL/2.0/. 11 * 12 * See the COPYRIGHT file distributed with this work for additional 13 * information regarding copyright ownership. 14 */ 15 16 #include <limits.h> 17 #include <stdio.h> 18 #include <stdlib.h> 19 #include <string.h> 20 #include <unistd.h> 21 22 #include <openssl/crypto.h> 23 #include <openssl/opensslv.h> 24 #if OPENSSL_VERSION_NUMBER >= 0x30000000L && OPENSSL_API_LEVEL >= 30000 25 #include <openssl/provider.h> 26 #endif 27 28 #include <isc/fips.h> 29 #include <isc/md.h> 30 #include <isc/mem.h> 31 #include <isc/net.h> 32 #include <isc/util.h> 33 34 #include <dns/edns.h> 35 36 #include <dst/dst.h> 37 38 static void 39 usage(void) { 40 fprintf(stderr, "usage: feature-test <arg>\n"); 41 fprintf(stderr, "args:\n"); 42 fprintf(stderr, "\t--edns-version\n"); 43 fprintf(stderr, "\t--enable-dnsrps\n"); 44 fprintf(stderr, "\t--enable-dnstap\n"); 45 fprintf(stderr, "\t--enable-querytrace\n"); 46 fprintf(stderr, "\t--fips-provider\n"); 47 fprintf(stderr, "\t--gethostname\n"); 48 fprintf(stderr, "\t--gssapi\n"); 49 fprintf(stderr, "\t--have-fips-dh\n"); 50 fprintf(stderr, "\t--have-fips-mode\n"); 51 fprintf(stderr, "\t--have-geoip2\n"); 52 fprintf(stderr, "\t--have-json-c\n"); 53 fprintf(stderr, "\t--have-libxml2\n"); 54 fprintf(stderr, "\t--have-openssl-cipher-suites\n"); 55 fprintf(stderr, "\t--ipv6only=no\n"); 56 fprintf(stderr, "\t--md5\n"); 57 fprintf(stderr, "\t--rsasha1\n"); 58 fprintf(stderr, "\t--tsan\n"); 59 fprintf(stderr, "\t--with-dlz-filesystem\n"); 60 fprintf(stderr, "\t--with-libidn2\n"); 61 fprintf(stderr, "\t--with-lmdb\n"); 62 fprintf(stderr, "\t--with-libnghttp2\n"); 63 fprintf(stderr, "\t--with-zlib\n"); 64 } 65 66 int 67 main(int argc, char **argv) { 68 if (argc != 2) { 69 usage(); 70 return 1; 71 } 72 73 if (strcmp(argv[1], "--edns-version") == 0) { 74 #ifdef DNS_EDNS_VERSION 75 printf("%d\n", DNS_EDNS_VERSION); 76 #else /* ifdef DNS_EDNS_VERSION */ 77 printf("0\n"); 78 #endif /* ifdef DNS_EDNS_VERSION */ 79 return 0; 80 } 81 82 if (strcmp(argv[1], "--enable-dnsrps") == 0) { 83 #ifdef USE_DNSRPS 84 return 0; 85 #else /* ifdef USE_DNSRPS */ 86 return 1; 87 #endif /* ifdef USE_DNSRPS */ 88 } 89 90 if (strcmp(argv[1], "--enable-dnstap") == 0) { 91 #ifdef HAVE_DNSTAP 92 return 0; 93 #else /* ifdef HAVE_DNSTAP */ 94 return 1; 95 #endif /* ifdef HAVE_DNSTAP */ 96 } 97 98 if (strcmp(argv[1], "--enable-querytrace") == 0) { 99 #ifdef WANT_QUERYTRACE 100 return 0; 101 #else /* ifdef WANT_QUERYTRACE */ 102 return 1; 103 #endif /* ifdef WANT_QUERYTRACE */ 104 } 105 106 if (strcasecmp(argv[1], "--fips-provider") == 0) { 107 #if OPENSSL_VERSION_NUMBER >= 0x30000000L && OPENSSL_API_LEVEL >= 30000 108 OSSL_PROVIDER *fips = OSSL_PROVIDER_load(NULL, "fips"); 109 if (fips != NULL) { 110 OSSL_PROVIDER_unload(fips); 111 } 112 return fips != NULL ? 0 : 1; 113 #else 114 return 1; 115 #endif 116 } 117 118 if (strcmp(argv[1], "--gethostname") == 0) { 119 char hostname[_POSIX_HOST_NAME_MAX + 1]; 120 int n; 121 122 n = gethostname(hostname, sizeof(hostname)); 123 if (n == -1) { 124 perror("gethostname"); 125 return 1; 126 } 127 fprintf(stdout, "%s\n", hostname); 128 return 0; 129 } 130 131 if (strcmp(argv[1], "--gssapi") == 0) { 132 #if HAVE_GSSAPI 133 return 0; 134 #else /* HAVE_GSSAPI */ 135 return 1; 136 #endif /* HAVE_GSSAPI */ 137 } 138 139 if (strcmp(argv[1], "--have-fips-dh") == 0) { 140 #if defined(ENABLE_FIPS_MODE) 141 #if OPENSSL_VERSION_NUMBER >= 0x30000000L && OPENSSL_API_LEVEL >= 30000 142 return 0; 143 #else 144 return 1; 145 #endif 146 #else 147 if (isc_fips_mode()) { 148 #if OPENSSL_VERSION_NUMBER >= 0x30000000L && OPENSSL_API_LEVEL >= 30000 149 return 0; 150 #else 151 return 1; 152 #endif 153 } 154 return 0; 155 #endif 156 } 157 158 if (strcmp(argv[1], "--have-fips-mode") == 0) { 159 #if defined(ENABLE_FIPS_MODE) 160 return 0; 161 #else 162 return isc_fips_mode() ? 0 : 1; 163 #endif 164 } 165 166 if (strcmp(argv[1], "--have-geoip2") == 0) { 167 #ifdef HAVE_GEOIP2 168 return 0; 169 #else /* ifdef HAVE_GEOIP2 */ 170 return 1; 171 #endif /* ifdef HAVE_GEOIP2 */ 172 } 173 174 if (strcmp(argv[1], "--have-json-c") == 0) { 175 #ifdef HAVE_JSON_C 176 return 0; 177 #else /* ifdef HAVE_JSON_C */ 178 return 1; 179 #endif /* ifdef HAVE_JSON_C */ 180 } 181 182 if (strcmp(argv[1], "--have-libxml2") == 0) { 183 #ifdef HAVE_LIBXML2 184 return 0; 185 #else /* ifdef HAVE_LIBXML2 */ 186 return 1; 187 #endif /* ifdef HAVE_LIBXML2 */ 188 } 189 190 if (strcmp(argv[1], "--have-openssl-cipher-suites") == 0) { 191 #ifdef HAVE_SSL_CTX_SET_CIPHERSUITES 192 return 0; 193 #else /* ifdef HAVE_SSL_CTX_SET_CIPHERSUITES */ 194 return 1; 195 #endif /* ifdef HAVE_SSL_CTX_SET_CIPHERSUITES */ 196 } 197 198 if (strcmp(argv[1], "--tsan") == 0) { 199 #if defined(__has_feature) 200 #if __has_feature(thread_sanitizer) 201 return 0; 202 #endif 203 #endif 204 #if __SANITIZE_THREAD__ 205 return 0; 206 #else 207 return 1; 208 #endif 209 } 210 211 if (strcmp(argv[1], "--md5") == 0) { 212 isc_mem_t *mctx = NULL; 213 int answer; 214 215 isc_mem_create(&mctx); 216 dst_lib_init(mctx, NULL); 217 answer = dst_algorithm_supported(DST_ALG_HMACMD5) ? 0 : 1; 218 dst_lib_destroy(); 219 isc_mem_detach(&mctx); 220 return answer; 221 } 222 223 if (strcmp(argv[1], "--ipv6only=no") == 0) { 224 #if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY) 225 int s; 226 int n = -1; 227 int v6only = -1; 228 socklen_t len = sizeof(v6only); 229 230 s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); 231 if (s >= 0) { 232 n = getsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, 233 (void *)&v6only, &len); 234 close(s); 235 } 236 return (n == 0 && v6only == 0) ? 0 : 1; 237 #else /* defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY) */ 238 return 1; 239 #endif /* defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY) */ 240 } 241 242 if (strcasecmp(argv[1], "--rsasha1") == 0) { 243 int answer; 244 isc_mem_t *mctx = NULL; 245 isc_mem_create(&mctx); 246 dst_lib_init(mctx, NULL); 247 answer = dst_algorithm_supported(DST_ALG_RSASHA1) ? 0 : 1; 248 dst_lib_destroy(); 249 isc_mem_detach(&mctx); 250 return answer; 251 } 252 253 if (strcmp(argv[1], "--with-dlz-filesystem") == 0) { 254 #ifdef DLZ_FILESYSTEM 255 return 0; 256 #else /* ifdef DLZ_FILESYSTEM */ 257 return 1; 258 #endif /* ifdef DLZ_FILESYSTEM */ 259 } 260 261 if (strcmp(argv[1], "--with-libidn2") == 0) { 262 #ifdef HAVE_LIBIDN2 263 return 0; 264 #else /* ifdef HAVE_LIBIDN2 */ 265 return 1; 266 #endif /* ifdef HAVE_LIBIDN2 */ 267 } 268 269 if (strcmp(argv[1], "--with-lmdb") == 0) { 270 #ifdef HAVE_LMDB 271 return 0; 272 #else /* ifdef HAVE_LMDB */ 273 return 1; 274 #endif /* ifdef HAVE_LMDB */ 275 } 276 277 if (strcmp(argv[1], "--with-libnghttp2") == 0) { 278 #ifdef HAVE_LIBNGHTTP2 279 return 0; 280 #else /* ifdef HAVE_LIBNGHTTP2 */ 281 return 1; 282 #endif /* ifdef HAVE_LIBNGHTTP2 */ 283 } 284 285 if (strcmp(argv[1], "--with-zlib") == 0) { 286 #ifdef HAVE_ZLIB 287 return 0; 288 #else /* ifdef HAVE_ZLIB */ 289 return 1; 290 #endif /* ifdef HAVE_ZLIB */ 291 } 292 293 fprintf(stderr, "unknown arg: %s\n", argv[1]); 294 usage(); 295 return 1; 296 } 297