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