"Fossies" - the Fresh Open Source Software Archive 
Member "ospfctl/parser.c" (14 Oct 2007, 7449 Bytes) of package /linux/privat/old/openospfd-4.6.tgz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "parser.c" see the
Fossies "Dox" file reference documentation.
1 /* $OpenBSD: parser.c,v 1.15 2007/10/14 01:28:08 deraadt Exp $ */
2
3 /*
4 * Copyright (c) 2004 Esben Norby <norby@openbsd.org>
5 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20 #include <sys/types.h>
21 #include <sys/socket.h>
22 #include <netinet/in.h>
23 #include <arpa/inet.h>
24 #include <err.h>
25 #include <errno.h>
26 #include <limits.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30
31 #include "ospfd.h"
32
33 #include "parser.h"
34
35 enum token_type {
36 NOTOKEN,
37 ENDTOKEN,
38 KEYWORD,
39 ADDRESS,
40 FLAG,
41 PREFIX,
42 IFNAME
43 };
44
45 struct token {
46 enum token_type type;
47 const char *keyword;
48 int value;
49 const struct token *next;
50 };
51
52 static const struct token t_main[];
53 static const struct token t_fib[];
54 static const struct token t_show[];
55 static const struct token t_show_iface[];
56 static const struct token t_show_db[];
57 static const struct token t_show_area[];
58 static const struct token t_show_nbr[];
59 static const struct token t_show_rib[];
60 static const struct token t_show_fib[];
61
62 static const struct token t_main[] = {
63 {KEYWORD, "reload", RELOAD, NULL},
64 {KEYWORD, "fib", FIB, t_fib},
65 {KEYWORD, "show", SHOW, t_show},
66 {ENDTOKEN, "", NONE, NULL}
67 };
68
69 static const struct token t_fib[] = {
70 { KEYWORD, "couple", FIB_COUPLE, NULL},
71 { KEYWORD, "decouple", FIB_DECOUPLE, NULL},
72 { ENDTOKEN, "", NONE, NULL}
73 };
74
75 static const struct token t_show[] = {
76 {NOTOKEN, "", NONE, NULL},
77 {KEYWORD, "interfaces", SHOW_IFACE, t_show_iface},
78 {KEYWORD, "database", SHOW_DB, t_show_db},
79 {KEYWORD, "neighbor", SHOW_NBR, t_show_nbr},
80 {KEYWORD, "rib", SHOW_RIB, t_show_rib},
81 {KEYWORD, "fib", SHOW_FIB, t_show_fib},
82 {KEYWORD, "summary", SHOW_SUM, NULL},
83 {ENDTOKEN, "", NONE, NULL}
84 };
85
86 static const struct token t_show_iface[] = {
87 {NOTOKEN, "", NONE, NULL},
88 {KEYWORD, "detail", SHOW_IFACE_DTAIL, NULL},
89 {IFNAME, "", SHOW_IFACE_DTAIL, NULL},
90 {ENDTOKEN, "", NONE, NULL}
91 };
92
93 static const struct token t_show_db[] = {
94 {NOTOKEN, "", NONE, NULL},
95 {KEYWORD, "area", SHOW_DBBYAREA, t_show_area},
96 {KEYWORD, "asbr", SHOW_DBASBR, NULL},
97 {KEYWORD, "external", SHOW_DBEXT, NULL},
98 {KEYWORD, "network", SHOW_DBNET, NULL},
99 {KEYWORD, "router", SHOW_DBRTR, NULL},
100 {KEYWORD, "self-originated", SHOW_DBSELF, NULL},
101 {KEYWORD, "summary", SHOW_DBSUM, NULL},
102 {ENDTOKEN, "", NONE, NULL}
103 };
104
105 static const struct token t_show_area[] = {
106 {ADDRESS, "", NONE, NULL},
107 {ENDTOKEN, "", NONE, NULL}
108 };
109
110 static const struct token t_show_nbr[] = {
111 {NOTOKEN, "", NONE, NULL},
112 {KEYWORD, "detail", SHOW_NBR_DTAIL, NULL},
113 {ENDTOKEN, "", NONE, NULL}
114 };
115
116 static const struct token t_show_rib[] = {
117 {NOTOKEN, "", NONE, NULL},
118 {KEYWORD, "detail", SHOW_RIB_DTAIL, NULL},
119 {ENDTOKEN, "", NONE, NULL}
120 };
121
122 static const struct token t_show_fib[] = {
123 {NOTOKEN, "", NONE, NULL},
124 {KEYWORD, "interface", SHOW_FIB_IFACE, t_show_iface},
125 {FLAG, "connected", F_CONNECTED, t_show_fib},
126 {FLAG, "static", F_STATIC, t_show_fib},
127 {FLAG, "ospf", F_OSPFD_INSERTED, t_show_fib},
128 {ADDRESS, "", NONE, NULL},
129 {ENDTOKEN, "", NONE, NULL}
130 };
131
132 static struct parse_result res;
133
134 struct parse_result *
135 parse(int argc, char *argv[])
136 {
137 const struct token *table = t_main;
138 const struct token *match;
139
140 bzero(&res, sizeof(res));
141
142 while (argc >= 0) {
143 if ((match = match_token(argv[0], table)) == NULL) {
144 fprintf(stderr, "valid commands/args:\n");
145 show_valid_args(table);
146 return (NULL);
147 }
148
149 argc--;
150 argv++;
151
152 if (match->type == NOTOKEN || match->next == NULL)
153 break;
154
155 table = match->next;
156 }
157
158 if (argc > 0) {
159 fprintf(stderr, "superfluous argument: %s\n", argv[0]);
160 return (NULL);
161 }
162
163 return (&res);
164 }
165
166 const struct token *
167 match_token(const char *word, const struct token table[])
168 {
169 u_int i, match;
170 const struct token *t = NULL;
171
172 match = 0;
173
174 for (i = 0; table[i].type != ENDTOKEN; i++) {
175 switch (table[i].type) {
176 case NOTOKEN:
177 if (word == NULL || strlen(word) == 0) {
178 match++;
179 t = &table[i];
180 }
181 break;
182 case KEYWORD:
183 if (word != NULL && strncmp(word, table[i].keyword,
184 strlen(word)) == 0) {
185 match++;
186 t = &table[i];
187 if (t->value)
188 res.action = t->value;
189 }
190 break;
191 case FLAG:
192 if (word != NULL && strncmp(word, table[i].keyword,
193 strlen(word)) == 0) {
194 match++;
195 t = &table[i];
196 res.flags |= t->value;
197 }
198 break;
199 case ADDRESS:
200 if (parse_addr(word, &res.addr)) {
201 match++;
202 t = &table[i];
203 if (t->value)
204 res.action = t->value;
205 }
206 break;
207 case PREFIX:
208 if (parse_prefix(word, &res.addr, &res.prefixlen)) {
209 match++;
210 t = &table[i];
211 if (t->value)
212 res.action = t->value;
213 }
214 break;
215 case IFNAME:
216 if (!match && word != NULL && strlen(word) > 0) {
217 if (strlcpy(res.ifname, word,
218 sizeof(res.ifname)) >=
219 sizeof(res.ifname))
220 err(1, "interface name too long");
221 match++;
222 t = &table[i];
223 if (t->value)
224 res.action = t->value;
225 }
226 break;
227
228 case ENDTOKEN:
229 break;
230 }
231 }
232
233 if (match != 1) {
234 if (word == NULL)
235 fprintf(stderr, "missing argument:\n");
236 else if (match > 1)
237 fprintf(stderr, "ambiguous argument: %s\n", word);
238 else if (match < 1)
239 fprintf(stderr, "unknown argument: %s\n", word);
240 return (NULL);
241 }
242
243 return (t);
244 }
245
246 void
247 show_valid_args(const struct token table[])
248 {
249 int i;
250
251 for (i = 0; table[i].type != ENDTOKEN; i++) {
252 switch (table[i].type) {
253 case NOTOKEN:
254 fprintf(stderr, " <cr>\n");
255 break;
256 case KEYWORD:
257 case FLAG:
258 fprintf(stderr, " %s\n", table[i].keyword);
259 break;
260 case ADDRESS:
261 fprintf(stderr, " <address>\n");
262 break;
263 case PREFIX:
264 fprintf(stderr, " <address>[/<len>]\n");
265 break;
266 case IFNAME:
267 fprintf(stderr, " <interface>\n");
268 break;
269 case ENDTOKEN:
270 break;
271 }
272 }
273 }
274
275 int
276 parse_addr(const char *word, struct in_addr *addr)
277 {
278 struct in_addr ina;
279
280 if (word == NULL)
281 return (0);
282
283 bzero(addr, sizeof(struct in_addr));
284 bzero(&ina, sizeof(ina));
285
286 if (inet_pton(AF_INET, word, &ina)) {
287 addr->s_addr = ina.s_addr;
288 return (1);
289 }
290
291 return (0);
292 }
293
294 int
295 parse_prefix(const char *word, struct in_addr *addr, u_int8_t *prefixlen)
296 {
297 struct in_addr ina;
298 int bits = 32;
299
300 if (word == NULL)
301 return (0);
302
303 bzero(addr, sizeof(struct in_addr));
304 bzero(&ina, sizeof(ina));
305
306 if (strrchr(word, '/') != NULL) {
307 if ((bits = inet_net_pton(AF_INET, word,
308 &ina, sizeof(ina))) == -1)
309 return (0);
310 addr->s_addr = ina.s_addr & htonl(prefixlen2mask(bits));
311 *prefixlen = bits;
312 return (1);
313 }
314 *prefixlen = 32;
315 return (parse_addr(word, addr));
316 }
317
318 /* XXX local copy from kroute.c, should go to shared file */
319 in_addr_t
320 prefixlen2mask(u_int8_t prefixlen)
321 {
322 if (prefixlen == 0)
323 return (0);
324
325 return (0xffffffff << (32 - prefixlen));
326 }