1 /* $NetBSD: dnsrps.c,v 1.9 2025/01/26 16:25:00 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 /* 17 * -a exit(EXIT_SUCCESS) if dnsrps is available or dlopen() msg if not 18 * -n domain print the serial number of a domain to check if a new 19 * version of a policy zone is ready. 20 * Exit(1) if dnsrps is not available 21 * -w sec.ond wait for seconds, because `sleep 0.1` is not portable 22 */ 23 24 #include <errno.h> 25 #include <inttypes.h> 26 #include <stdbool.h> 27 #include <stdint.h> 28 #include <stdio.h> 29 #include <stdlib.h> 30 #include <string.h> 31 #include <sys/stat.h> 32 #include <sys/types.h> 33 #include <unistd.h> 34 35 #include <isc/util.h> 36 37 #ifdef USE_DNSRPS 38 #include <dns/librpz.h> 39 #else /* ifdef USE_DNSRPS */ 40 typedef struct { 41 char c[120]; 42 } librpz_emsg_t; 43 #endif /* ifdef USE_DNSRPS */ 44 45 static bool 46 link_dnsrps(librpz_emsg_t *emsg); 47 48 #define USAGE "usage: [-a] [-n domain] [-w sec.onds]\n" 49 50 int 51 main(int argc, char **argv) { 52 #ifdef USE_DNSRPS 53 char cstr[sizeof("zone ") + 1024 + 10]; 54 librpz_clist_t *clist = NULL; 55 librpz_client_t *client = NULL; 56 librpz_rsp_t *rsp = NULL; 57 uint32_t serial; 58 #endif /* ifdef USE_DNSRPS */ 59 double seconds; 60 librpz_emsg_t emsg; 61 char *p; 62 int i; 63 64 while ((i = getopt(argc, argv, "an:w:")) != -1) { 65 switch (i) { 66 case 'a': 67 if (!link_dnsrps(&emsg)) { 68 printf("I:%s\n", emsg.c); 69 return 1; 70 } 71 return 0; 72 73 case 'n': 74 if (!link_dnsrps(&emsg)) { 75 fprintf(stderr, "## %s\n", emsg.c); 76 return 1; 77 } 78 #ifdef USE_DNSRPS 79 /* 80 * Get the serial number of a policy zone. 81 */ 82 clist = librpz->clist_create(&emsg, NULL, NULL, NULL, 83 NULL, NULL); 84 if (clist == NULL) { 85 fprintf(stderr, "## %s: %s\n", optarg, emsg.c); 86 return 1; 87 } 88 snprintf(cstr, sizeof(cstr), "zone %s;", optarg); 89 client = librpz->client_create(&emsg, clist, cstr, 90 true); 91 if (client == NULL) { 92 fprintf(stderr, "## %s\n", emsg.c); 93 librpz->clist_detach(&clist); 94 return 1; 95 } 96 97 rsp = NULL; 98 if (!librpz->rsp_create(&emsg, &rsp, NULL, client, true, 99 false) || 100 rsp == NULL) 101 { 102 fprintf(stderr, "## %s\n", emsg.c); 103 librpz->client_detach(&client); 104 librpz->clist_detach(&clist); 105 return 1; 106 } 107 108 if (!librpz->soa_serial(&emsg, &serial, optarg, rsp)) { 109 fprintf(stderr, "## %s\n", emsg.c); 110 librpz->rsp_detach(&rsp); 111 librpz->client_detach(&client); 112 librpz->clist_detach(&clist); 113 return 1; 114 } 115 librpz->rsp_detach(&rsp); 116 librpz->client_detach(&client); 117 librpz->clist_detach(&clist); 118 printf("%u\n", serial); 119 #else /* ifdef USE_DNSRPS */ 120 UNREACHABLE(); 121 #endif /* ifdef USE_DNSRPS */ 122 return 0; 123 124 case 'w': 125 seconds = strtod(optarg, &p); 126 if (seconds <= 0 || *p != '\0') { 127 fprintf(stderr, USAGE); 128 return 1; 129 } 130 usleep((int)(seconds * 1000.0 * 1000.0)); 131 return 0; 132 133 default: 134 fprintf(stderr, USAGE); 135 return 1; 136 } 137 } 138 fprintf(stderr, USAGE); 139 return 1; 140 } 141 142 static bool 143 link_dnsrps(librpz_emsg_t *emsg) { 144 #ifdef USE_DNSRPS 145 librpz = librpz_lib_open(emsg, NULL, LIBRPZ_LIB_OPEN); 146 if (librpz == NULL) { 147 return false; 148 } 149 150 return true; 151 #else /* ifdef USE_DNSRPS */ 152 snprintf(emsg->c, sizeof(emsg->c), "DNSRPS not configured"); 153 return false; 154 #endif /* ifdef USE_DNSRPS */ 155 } 156