ISC DHCP  4.4.2b1
A reference DHCPv4 and DHCPv6 implementation
keama.c
Go to the documentation of this file.
1 /*
2  * Copyright(c) 2017-2019 by 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  * 950 Charter Street
18  * Redwood City, CA 94063
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 
50 int local_family = 0;
51 char *hook_library_path = NULL;
52 char *input_file = NULL;
53 char *output_file = NULL;
54 FILE *input = NULL;
55 FILE *output = NULL;
59 
60 static const char use_noarg[] = "No argument for command: %s";
61 static const char bad_resolve[] = "Bad -r argument: %s";
62 
63 int
64 main(int argc, char **argv) {
65  int i, fd;
66  char *inbuf = NULL;
67  size_t oldsize = 0;
68  size_t newsize = 0;
69  ssize_t cc;
70  struct parse *cfile;
71  size_t cnt = 0;
72 
73  for (i = 1; i < argc; i++) {
74  if (strcmp(argv[i], "-4") == 0)
75  local_family = AF_INET;
76  else if (strcmp(argv[i], "-6") == 0)
77  local_family = AF_INET6;
78  else if (strcmp(argv[i], "-D") == 0)
80  else if (strcmp(argv[i], "-N") == 0)
82  else if (strcmp(argv[i], "-T") == 0)
83  json = ISC_TRUE;
84  else if (strcmp(argv[i], "-r") == 0) {
85  if (++i == argc)
86  usage(use_noarg, argv[i - 1]);
87  if (strcmp(argv[i], "perform") == 0)
88  resolve = perform;
89  else if (strcmp(argv[i], "fatal") == 0)
90  resolve = fatal;
91  else if (strcmp(argv[i], "pass") == 0)
92  resolve = pass;
93  else
94  usage(bad_resolve, argv[i]);
95  } else if (strcmp(argv[i], "-l") == 0) {
96  if (++i == argc)
97  usage(use_noarg, argv[i - 1]);
98  hook_library_path = argv[i];
99  } else if (strcmp(argv[i], "-i") == 0) {
100  if (++i == argc)
101  usage(use_noarg, argv[i - 1]);
102  input_file = argv[i];
103  } else if (strcmp(argv[i], "-o") == 0) {
104  if (++i == argc)
105  usage(use_noarg, argv[i - 1]);
106  output_file = argv[i];
107  } else
108  usage("Unknown command: %s", argv[i]);
109  }
110 
111  if (!json && (local_family == 0))
112  usage("address family must be set using %s", "-4 or -6");
113 
114  if (input_file == NULL) {
115  input_file = "--stdin--";
116  fd = fileno(stdin);
117  for (;;) {
118  if (newsize == 0)
119  newsize = 1024;
120  else {
121  oldsize = newsize;
122  newsize *= 4;
123  }
124  inbuf = (char *)realloc(inbuf, newsize);
125  if (inbuf == 0)
126  usage("out of memory reading standard "
127  "input: %s", strerror(errno));
128  cc = read(fd, inbuf + oldsize, newsize - oldsize);
129  if (cc < 0)
130  usage("error reading standard input: %s",
131  strerror(errno));
132  if (cc + oldsize < newsize) {
133  newsize = cc + oldsize;
134  break;
135  }
136  }
137  } else {
138  fd = open(input_file, O_RDONLY);
139  if (fd < 0)
140  usage("Cannot open '%s' for reading", input_file);
141  }
142 
143  if (output_file) {
144  output = fopen(output_file, "w");
145  if (output == NULL)
146  usage("Cannot open '%s' for writing", output_file);
147  } else
148  output = stdout;
149 
150  TAILQ_INIT(&parses);
151  cfile = new_parse(fd, inbuf, newsize, input_file, 0);
152  assert(cfile != NULL);
153 
154  if (json) {
155  struct element *elem;
156 
157  elem = json_parse(cfile);
158  if (elem != NULL) {
159  print(output, elem, 0, 0);
160  fprintf(output, "\n");
161  }
162  } else {
163  spaces_init();
164  options_init();
165  cnt = conf_file_parse(cfile);
166  if (cfile->stack_top > 0) {
167  print(output, cfile->stack[0], 0, 0);
168  fprintf(output, "\n");
169  }
170  }
171 
172  end_parse(cfile);
173 
174  exit(cnt);
175 }
176 
177 void
178 stackPush(struct parse *pc, struct element *elem)
179 {
180  if (pc->stack_top + 2 >= pc->stack_size) {
181  size_t new_size = pc->stack_size + 10;
182  size_t amount = new_size * sizeof(struct element *);
183 
184  pc->stack = (struct element **)realloc(pc->stack, amount);
185  if (pc->stack == NULL)
186  parse_error(pc, "can't resize element stack");
187  pc->stack_size = new_size;
188  }
189  pc->stack_top++;
190  pc->stack[pc->stack_top] = elem;
191 }
192 
193 void
194 parse_error(struct parse *cfile, const char *fmt, ...)
195 {
196  va_list list;
197  char lexbuf[256];
198  char mbuf[1024];
199  char fbuf[1024];
200  unsigned i, lix;
201 
202  snprintf(fbuf, sizeof(fbuf), "%s line %d: %s",
203  cfile->tlname, cfile->lexline, fmt);
204 
205  va_start(list, fmt);
206  vsnprintf(mbuf, sizeof(mbuf), fbuf, list);
207  va_end(list);
208 
209  lix = 0;
210  for (i = 0;
211  cfile->token_line[i] && i < (cfile->lexchar - 1); i++) {
212  if (lix < sizeof(lexbuf) - 1)
213  lexbuf[lix++] = ' ';
214  if (cfile->token_line[i] == '\t') {
215  for (; lix < (sizeof lexbuf) - 1 && (lix & 7); lix++)
216  lexbuf[lix] = ' ';
217  }
218  }
219  lexbuf[lix] = 0;
220 
221  fprintf(stderr, "%s\n%s\n", mbuf, cfile->token_line);
222  if (cfile->lexchar < 81)
223  fprintf(stderr, "%s^\n", lexbuf);
224  exit(-1);
225 }
isc_result_t end_parse(struct parse **cfile)
Definition: conflex.c:103
isc_result_t new_parse(struct parse **cfile, int file, char *inbuf, unsigned buflen, const char *name, int eolp)
Definition: conflex.c:41
void print(FILE *fp, const struct element *e, isc_boolean_t skip, unsigned indent)
Definition: data.c:919
#define TAILQ_INIT(head)
Definition: data.h:72
isc_boolean_t
Definition: data.h:150
#define ISC_TRUE
Definition: data.h:153
#define ISC_FALSE
Definition: data.h:152
struct element * json_parse(struct parse *cfile)
Definition: json.c:32
int local_family
Definition: keama.c:50
isc_boolean_t json
Definition: keama.c:58
char * hook_library_path
Definition: keama.c:51
int main(int argc, char **argv)
Definition: keama.c:64
char * output_file
Definition: keama.c:53
#define KEAMA_USAGE
Definition: keama.c:35
char * input_file
Definition: keama.c:52
isc_boolean_t use_isc_lifetimes
Definition: keama.c:56
void parse_error(struct parse *cfile, const char *fmt,...)
Definition: keama.c:194
FILE * output
Definition: keama.c:55
void stackPush(struct parse *pc, struct element *elem)
Definition: keama.c:178
FILE * input
Definition: keama.c:54
isc_boolean_t global_hr
Definition: keama.c:57
size_t conf_file_parse(struct parse *)
resolve
Definition: keama.h:34
@ pass
Definition: keama.h:37
@ perform
Definition: keama.h:35
@ fatal
Definition: keama.h:36
void options_init(void)
Definition: options.c:419
void spaces_init(void)
Definition: options.c:399
Definition: data.h:216
Definition: dhcpd.h:288
int lexline
Definition: dhcpd.h:289
size_t stack_size
Definition: keama.h:111
char * token_line
Definition: dhcpd.h:291
const char * tlname
Definition: dhcpd.h:294
size_t stack_top
Definition: keama.h:112
int lexchar
Definition: dhcpd.h:290
char * inbuf
Definition: dhcpd.h:328
struct element ** stack
Definition: keama.h:110