1 /* $NetBSD: keama.c,v 1.3 2022/04/03 01:10:59 christos Exp $ */ 2 3 /* 4 * Copyright(C) 2017-2022 Internet Systems Consortium, Inc.("ISC") 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 * 18 * Internet Systems Consortium, Inc. 19 * PO Box 360 20 * Newmarket, NH 03857 USA 21 * <info@isc.org> 22 * https://www.isc.org/ 23 * 24 */ 25 26 #include <sys/cdefs.h> 27 __RCSID("$NetBSD: keama.c,v 1.3 2022/04/03 01:10:59 christos Exp $"); 28 29 #include <sys/errno.h> 30 #include <arpa/inet.h> 31 #include <assert.h> 32 #include <fcntl.h> 33 #include <stdarg.h> 34 #include <stdlib.h> 35 #include <string.h> 36 #include <unistd.h> 37 38 #include "keama.h" 39 40 #define KEAMA_USAGE "Usage: keama [-4|-6] [-D] [-N]" \ 41 " [-r {perform|fatal|pass}\\n" \ 42 " [-l hook-library-path]" \ 43 " [-i input-file] [-o output-file]\n" 44 45 static void 46 usage(const char *sfmt, const char *sarg) { 47 if (sfmt != NULL) { 48 fprintf(stderr, sfmt, sarg); 49 fprintf(stderr, "\n"); 50 } 51 fputs(KEAMA_USAGE, stderr); 52 exit(1); 53 } 54 55 enum resolve resolve; 56 struct parses parses; 57 58 int local_family = 0; 59 char *hook_library_path = NULL; 60 char *input_file = NULL; 61 char *output_file = NULL; 62 FILE *input = NULL; 63 FILE *output = NULL; 64 isc_boolean_t use_isc_lifetimes = ISC_FALSE; 65 isc_boolean_t global_hr = ISC_TRUE; 66 isc_boolean_t json = ISC_FALSE; 67 68 static const char use_noarg[] = "No argument for command: %s"; 69 static const char bad_resolve[] = "Bad -r argument: %s"; 70 71 int 72 main(int argc, char **argv) { 73 int i, fd; 74 char *inbuf = NULL; 75 size_t oldsize = 0; 76 size_t newsize = 0; 77 ssize_t cc; 78 struct parse *cfile; 79 size_t cnt = 0; 80 81 for (i = 1; i < argc; i++) { 82 if (strcmp(argv[i], "-4") == 0) 83 local_family = AF_INET; 84 else if (strcmp(argv[i], "-6") == 0) 85 local_family = AF_INET6; 86 else if (strcmp(argv[i], "-D") == 0) 87 use_isc_lifetimes = ISC_TRUE; 88 else if (strcmp(argv[i], "-N") == 0) 89 global_hr = ISC_FALSE; 90 else if (strcmp(argv[i], "-T") == 0) 91 json = ISC_TRUE; 92 else if (strcmp(argv[i], "-r") == 0) { 93 if (++i == argc) 94 usage(use_noarg, argv[i - 1]); 95 if (strcmp(argv[i], "perform") == 0) 96 resolve = perform; 97 else if (strcmp(argv[i], "fatal") == 0) 98 resolve = fatal; 99 else if (strcmp(argv[i], "pass") == 0) 100 resolve = pass; 101 else 102 usage(bad_resolve, argv[i]); 103 } else if (strcmp(argv[i], "-l") == 0) { 104 if (++i == argc) 105 usage(use_noarg, argv[i - 1]); 106 hook_library_path = argv[i]; 107 } else if (strcmp(argv[i], "-i") == 0) { 108 if (++i == argc) 109 usage(use_noarg, argv[i - 1]); 110 input_file = argv[i]; 111 } else if (strcmp(argv[i], "-o") == 0) { 112 if (++i == argc) 113 usage(use_noarg, argv[i - 1]); 114 output_file = argv[i]; 115 } else 116 usage("Unknown command: %s", argv[i]); 117 } 118 119 if (!json && (local_family == 0)) 120 usage("address family must be set using %s", "-4 or -6"); 121 122 if (input_file == NULL) { 123 input_file = "--stdin--"; 124 fd = fileno(stdin); 125 for (;;) { 126 if (newsize == 0) 127 newsize = 1024; 128 else { 129 oldsize = newsize; 130 newsize *= 4; 131 } 132 inbuf = (char *)realloc(inbuf, newsize); 133 if (inbuf == 0) 134 usage("out of memory reading standard " 135 "input: %s", strerror(errno)); 136 cc = read(fd, inbuf + oldsize, newsize - oldsize); 137 if (cc < 0) 138 usage("error reading standard input: %s", 139 strerror(errno)); 140 if (cc + oldsize < newsize) { 141 newsize = cc + oldsize; 142 break; 143 } 144 } 145 } else { 146 fd = open(input_file, O_RDONLY); 147 if (fd < 0) 148 usage("Cannot open '%s' for reading", input_file); 149 } 150 151 if (output_file) { 152 output = fopen(output_file, "w"); 153 if (output == NULL) 154 usage("Cannot open '%s' for writing", output_file); 155 } else 156 output = stdout; 157 158 TAILQ_INIT(&parses); 159 cfile = new_parse(fd, inbuf, newsize, input_file, 0); 160 assert(cfile != NULL); 161 162 if (json) { 163 struct element *elem; 164 165 elem = json_parse(cfile); 166 if (elem != NULL) { 167 print(output, elem, 0, 0); 168 fprintf(output, "\n"); 169 } 170 } else { 171 spaces_init(); 172 options_init(); 173 cnt = conf_file_parse(cfile); 174 if (cfile->stack_top > 0) { 175 print(output, cfile->stack[0], 0, 0); 176 fprintf(output, "\n"); 177 } 178 } 179 180 end_parse(cfile); 181 182 exit(cnt); 183 } 184 185 void 186 stackPush(struct parse *pc, struct element *elem) 187 { 188 if (pc->stack_top + 2 >= pc->stack_size) { 189 size_t new_size = pc->stack_size + 10; 190 size_t amount = new_size * sizeof(struct element *); 191 192 pc->stack = (struct element **)realloc(pc->stack, amount); 193 if (pc->stack == NULL) 194 parse_error(pc, "can't resize element stack"); 195 pc->stack_size = new_size; 196 } 197 pc->stack_top++; 198 pc->stack[pc->stack_top] = elem; 199 } 200 201 void 202 parse_error(struct parse *cfile, const char *fmt, ...) 203 { 204 va_list list; 205 char lexbuf[256]; 206 char mbuf[1024]; 207 char fbuf[1024]; 208 unsigned i, lix; 209 210 snprintf(fbuf, sizeof(fbuf), "%s line %d: %s", 211 cfile->tlname, cfile->lexline, fmt); 212 213 va_start(list, fmt); 214 vsnprintf(mbuf, sizeof(mbuf), fbuf, list); 215 va_end(list); 216 217 lix = 0; 218 for (i = 0; 219 cfile->token_line[i] && i < (cfile->lexchar - 1); i++) { 220 if (lix < sizeof(lexbuf) - 1) 221 lexbuf[lix++] = ' '; 222 if (cfile->token_line[i] == '\t') { 223 for (; lix < (sizeof lexbuf) - 1 && (lix & 7); lix++) 224 lexbuf[lix] = ' '; 225 } 226 } 227 lexbuf[lix] = 0; 228 229 fprintf(stderr, "%s\n%s\n", mbuf, cfile->token_line); 230 if (cfile->lexchar < 81) 231 fprintf(stderr, "%s^\n", lexbuf); 232 exit(-1); 233 } 234