Bug Summary

File:src/usr.sbin/bgpctl/parser.c
Warning:line 731, column 34
The left operand of '&' is a garbage value

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name parser.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.sbin/bgpctl/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/usr.sbin/bgpctl -I /usr/src/usr.sbin/bgpctl/../bgpd -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.sbin/bgpctl/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.sbin/bgpctl/parser.c
1/* $OpenBSD: parser.c,v 1.107 2021/08/09 08:24:36 claudio Exp $ */
2
3/*
4 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
5 * Copyright (c) 2016 Job Snijders <job@instituut.net>
6 * Copyright (c) 2016 Peter Hessler <phessler@openbsd.org>
7 *
8 * Permission to use, copy, modify, and distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 */
20
21#include <sys/types.h>
22
23#include <endian.h>
24#include <err.h>
25#include <errno(*__errno()).h>
26#include <fcntl.h>
27#include <limits.h>
28#include <netdb.h>
29#include <stdio.h>
30#include <stdlib.h>
31#include <string.h>
32#include <unistd.h>
33
34#include "parser.h"
35
36enum token_type {
37 NOTOKEN,
38 ENDTOKEN,
39 KEYWORD,
40 ADDRESS,
41 PEERADDRESS,
42 FLAG,
43 ASNUM,
44 ASTYPE,
45 PREFIX,
46 PEERDESC,
47 GROUPDESC,
48 RIBNAME,
49 COMMUNICATION,
50 COMMUNITY,
51 EXTCOMMUNITY,
52 EXTCOM_SUBTYPE,
53 LARGE_COMMUNITY,
54 LOCALPREF,
55 MED,
56 NEXTHOP,
57 PFTABLE,
58 PREPNBR,
59 PREPSELF,
60 WEIGHT,
61 RD,
62 FAMILY,
63 RTABLE,
64 FILENAME,
65 PATHID,
66};
67
68struct token {
69 enum token_type type;
70 const char *keyword;
71 int value;
72 const struct token *next;
73};
74
75static const struct token t_main[];
76static const struct token t_show[];
77static const struct token t_show_summary[];
78static const struct token t_show_fib[];
79static const struct token t_show_rib[];
80static const struct token t_show_ovs[];
81static const struct token t_show_mrt[];
82static const struct token t_show_mrt_file[];
83static const struct token t_show_rib_neigh[];
84static const struct token t_show_mrt_neigh[];
85static const struct token t_show_rib_rib[];
86static const struct token t_show_neighbor[];
87static const struct token t_show_neighbor_modifiers[];
88static const struct token t_fib[];
89static const struct token t_neighbor[];
90static const struct token t_neighbor_modifiers[];
91static const struct token t_show_rib_as[];
92static const struct token t_show_mrt_as[];
93static const struct token t_show_prefix[];
94static const struct token t_show_ip[];
95static const struct token t_show_community[];
96static const struct token t_show_extcommunity[];
97static const struct token t_show_ext_subtype[];
98static const struct token t_show_largecommunity[];
99static const struct token t_network[];
100static const struct token t_network_show[];
101static const struct token t_prefix[];
102static const struct token t_set[];
103static const struct token t_community[];
104static const struct token t_extcommunity[];
105static const struct token t_ext_subtype[];
106static const struct token t_largecommunity[];
107static const struct token t_localpref[];
108static const struct token t_med[];
109static const struct token t_nexthop[];
110static const struct token t_pftable[];
111static const struct token t_prepnbr[];
112static const struct token t_prepself[];
113static const struct token t_weight[];
114static const struct token t_log[];
115static const struct token t_fib_table[];
116static const struct token t_show_fib_table[];
117static const struct token t_communication[];
118static const struct token t_show_rib_path[];
119
120static const struct token t_main[] = {
121 { KEYWORD, "reload", RELOAD, t_communication},
122 { KEYWORD, "show", SHOW, t_show},
123 { KEYWORD, "fib", FIB, t_fib},
124 { KEYWORD, "neighbor", NEIGHBOR, t_neighbor},
125 { KEYWORD, "network", NONE, t_network},
126 { KEYWORD, "log", NONE, t_log},
127 { ENDTOKEN, "", NONE, NULL((void *)0)}
128};
129
130static const struct token t_show[] = {
131 { NOTOKEN, "", NONE, NULL((void *)0)},
132 { KEYWORD, "fib", SHOW_FIB, t_show_fib},
133 { KEYWORD, "interfaces", SHOW_INTERFACE, NULL((void *)0)},
134 { KEYWORD, "neighbor", SHOW_NEIGHBOR, t_show_neighbor},
135 { KEYWORD, "network", NETWORK_SHOW, t_network_show},
136 { KEYWORD, "nexthop", SHOW_NEXTHOP, NULL((void *)0)},
137 { KEYWORD, "rib", SHOW_RIB, t_show_rib},
138 { KEYWORD, "tables", SHOW_FIB_TABLES, NULL((void *)0)},
139 { KEYWORD, "ip", NONE, t_show_ip},
140 { KEYWORD, "summary", SHOW_SUMMARY, t_show_summary},
141 { KEYWORD, "sets", SHOW_SET, NULL((void *)0)},
142 { KEYWORD, "rtr", SHOW_RTR, NULL((void *)0)},
143 { KEYWORD, "mrt", SHOW_MRT, t_show_mrt},
144 { ENDTOKEN, "", NONE, NULL((void *)0)}
145};
146
147static const struct token t_show_summary[] = {
148 { NOTOKEN, "", NONE, NULL((void *)0)},
149 { KEYWORD, "terse", SHOW_SUMMARY_TERSE, NULL((void *)0)},
150 { ENDTOKEN, "", NONE, NULL((void *)0)}
151};
152
153static const struct token t_show_fib[] = {
154 { NOTOKEN, "", NONE, NULL((void *)0)},
155 { FLAG, "connected", F_CONNECTED0x0004, t_show_fib},
156 { FLAG, "static", F_STATIC0x0020, t_show_fib},
157 { FLAG, "bgp", F_BGPD_INSERTED0x0001, t_show_fib},
158 { FLAG, "nexthop", F_NEXTHOP0x0008, t_show_fib},
159 { KEYWORD, "table", NONE, t_show_fib_table},
160 { FAMILY, "", NONE, t_show_fib},
161 { ADDRESS, "", NONE, NULL((void *)0)},
162 { ENDTOKEN, "", NONE, NULL((void *)0)}
163};
164
165static const struct token t_show_rib[] = {
166 { NOTOKEN, "", NONE, NULL((void *)0)},
167 { ASTYPE, "as", AS_ALL, t_show_rib_as},
168 { ASTYPE, "source-as", AS_SOURCE, t_show_rib_as},
169 { ASTYPE, "transit-as", AS_TRANSIT, t_show_rib_as},
170 { ASTYPE, "peer-as", AS_PEER, t_show_rib_as},
171 { ASTYPE, "empty-as", AS_EMPTY, t_show_rib},
172 { KEYWORD, "community", NONE, t_show_community},
173 { KEYWORD, "ext-community", NONE, t_show_extcommunity},
174 { KEYWORD, "large-community", NONE, t_show_largecommunity},
175 { FLAG, "best", F_CTL_ACTIVE0x8000, t_show_rib},
176 { FLAG, "selected", F_CTL_ACTIVE0x8000, t_show_rib},
177 { FLAG, "detail", F_CTL_DETAIL0x1000, t_show_rib},
178 { FLAG, "error", F_CTL_INVALID0x40000, t_show_rib},
179 { FLAG, "ssv" , F_CTL_SSV0x20000, t_show_rib},
180 { FLAG, "in", F_CTL_ADJ_IN0x2000, t_show_rib},
181 { FLAG, "out", F_CTL_ADJ_OUT0x4000, t_show_rib},
182 { KEYWORD, "neighbor", NONE, t_show_rib_neigh},
183 { KEYWORD, "ovs", NONE, t_show_ovs},
184 { KEYWORD, "path-id", NONE, t_show_rib_path},
185 { KEYWORD, "table", NONE, t_show_rib_rib},
186 { KEYWORD, "summary", SHOW_SUMMARY, t_show_summary},
187 { KEYWORD, "memory", SHOW_RIB_MEM, NULL((void *)0)},
188 { FAMILY, "", NONE, t_show_rib},
189 { PREFIX, "", NONE, t_show_prefix},
190 { ENDTOKEN, "", NONE, NULL((void *)0)}
191};
192
193static const struct token t_show_ovs[] = {
194 { FLAG, "valid" , F_CTL_OVS_VALID0x80000, t_show_rib},
195 { FLAG, "invalid", F_CTL_OVS_INVALID0x100000, t_show_rib},
196 { FLAG, "not-found", F_CTL_OVS_NOTFOUND0x200000, t_show_rib},
197 { ENDTOKEN, "", NONE, NULL((void *)0)}
198};
199
200static const struct token t_show_mrt[] = {
201 { NOTOKEN, "", NONE, NULL((void *)0)},
202 { ASTYPE, "as", AS_ALL, t_show_mrt_as},
203 { ASTYPE, "source-as", AS_SOURCE, t_show_mrt_as},
204 { ASTYPE, "transit-as", AS_TRANSIT, t_show_mrt_as},
205 { ASTYPE, "peer-as", AS_PEER, t_show_mrt_as},
206 { ASTYPE, "empty-as", AS_EMPTY, t_show_mrt},
207 { FLAG, "detail", F_CTL_DETAIL0x1000, t_show_mrt},
208 { FLAG, "ssv", F_CTL_SSV0x20000, t_show_mrt},
209 { KEYWORD, "neighbor", NONE, t_show_mrt_neigh},
210 { FLAG, "peers", F_CTL_NEIGHBORS0x400000,t_show_mrt},
211 { KEYWORD, "file", NONE, t_show_mrt_file},
212 { FAMILY, "", NONE, t_show_mrt},
213 { PREFIX, "", NONE, t_show_prefix},
214 { ENDTOKEN, "", NONE, NULL((void *)0)}
215};
216
217static const struct token t_show_mrt_file[] = {
218 { FILENAME, "", NONE, t_show_mrt},
219 { ENDTOKEN, "", NONE, NULL((void *)0)}
220};
221
222static const struct token t_show_rib_neigh_group[] = {
223 { GROUPDESC, "", NONE, t_show_rib},
224 { ENDTOKEN, "", NONE, NULL((void *)0)}
225};
226
227static const struct token t_show_rib_neigh[] = {
228 { KEYWORD, "group", NONE, t_show_rib_neigh_group},
229 { PEERADDRESS, "", NONE, t_show_rib},
230 { PEERDESC, "", NONE, t_show_rib},
231 { ENDTOKEN, "", NONE, NULL((void *)0)}
232};
233
234static const struct token t_show_mrt_neigh[] = {
235 { PEERADDRESS, "", NONE, t_show_mrt},
236 { ENDTOKEN, "", NONE, NULL((void *)0)}
237};
238
239static const struct token t_show_rib_rib[] = {
240 { RIBNAME, "", NONE, t_show_rib},
241 { ENDTOKEN, "", NONE, NULL((void *)0)}
242};
243
244static const struct token t_show_neighbor_modifiers[] = {
245 { NOTOKEN, "", NONE, NULL((void *)0)},
246 { KEYWORD, "timers", SHOW_NEIGHBOR_TIMERS, NULL((void *)0)},
247 { KEYWORD, "messages", SHOW_NEIGHBOR, NULL((void *)0)},
248 { KEYWORD, "terse", SHOW_NEIGHBOR_TERSE, NULL((void *)0)},
249 { ENDTOKEN, "", NONE, NULL((void *)0)}
250};
251
252static const struct token t_show_neighbor_group[] = {
253 { GROUPDESC, "", NONE, t_show_neighbor_modifiers},
254 { ENDTOKEN, "", NONE, NULL((void *)0)}
255};
256
257static const struct token t_show_neighbor[] = {
258 { NOTOKEN, "", NONE, NULL((void *)0)},
259 { KEYWORD, "group", NONE, t_show_neighbor_group},
260 { PEERADDRESS, "", NONE, t_show_neighbor_modifiers},
261 { PEERDESC, "", NONE, t_show_neighbor_modifiers},
262 { ENDTOKEN, "", NONE, NULL((void *)0)}
263};
264
265static const struct token t_fib[] = {
266 { KEYWORD, "couple", FIB_COUPLE, NULL((void *)0)},
267 { KEYWORD, "decouple", FIB_DECOUPLE, NULL((void *)0)},
268 { KEYWORD, "table", NONE, t_fib_table},
269 { ENDTOKEN, "", NONE, NULL((void *)0)}
270};
271
272static const struct token t_neighbor_group[] = {
273 { GROUPDESC, "", NONE, t_neighbor_modifiers},
274 { ENDTOKEN, "", NONE, NULL((void *)0)}
275};
276
277static const struct token t_neighbor[] = {
278 { KEYWORD, "group", NONE, t_neighbor_group},
279 { PEERADDRESS, "", NONE, t_neighbor_modifiers},
280 { PEERDESC, "", NONE, t_neighbor_modifiers},
281 { ENDTOKEN, "", NONE, NULL((void *)0)}
282};
283
284static const struct token t_communication[] = {
285 { NOTOKEN, "", NONE, NULL((void *)0)},
286 { COMMUNICATION, "", NONE, NULL((void *)0)},
287 { ENDTOKEN, "", NONE, NULL((void *)0)}
288};
289
290static const struct token t_neighbor_modifiers[] = {
291 { KEYWORD, "up", NEIGHBOR_UP, NULL((void *)0)},
292 { KEYWORD, "down", NEIGHBOR_DOWN, t_communication},
293 { KEYWORD, "clear", NEIGHBOR_CLEAR, t_communication},
294 { KEYWORD, "refresh", NEIGHBOR_RREFRESH, NULL((void *)0)},
295 { KEYWORD, "destroy", NEIGHBOR_DESTROY, NULL((void *)0)},
296 { ENDTOKEN, "", NONE, NULL((void *)0)}
297};
298
299static const struct token t_show_rib_as[] = {
300 { ASNUM, "", NONE, t_show_rib},
301 { ENDTOKEN, "", NONE, NULL((void *)0)}
302};
303
304static const struct token t_show_mrt_as[] = {
305 { ASNUM, "", NONE, t_show_mrt},
306 { ENDTOKEN, "", NONE, NULL((void *)0)}
307};
308
309static const struct token t_show_prefix[] = {
310 { NOTOKEN, "", NONE, NULL((void *)0)},
311 { FLAG, "all", F_LONGER0x0200, NULL((void *)0)},
312 { FLAG, "longer-prefixes", F_LONGER0x0200, NULL((void *)0)},
313 { FLAG, "or-longer", F_LONGER0x0200, NULL((void *)0)},
314 { FLAG, "or-shorter", F_SHORTER0x0400, NULL((void *)0)},
315 { ENDTOKEN, "", NONE, NULL((void *)0)}
316};
317
318static const struct token t_show_ip[] = {
319 { KEYWORD, "bgp", SHOW_RIB, t_show_rib},
320 { ENDTOKEN, "", NONE, NULL((void *)0)}
321};
322
323static const struct token t_show_community[] = {
324 { COMMUNITY, "", NONE, t_show_rib},
325 { ENDTOKEN, "", NONE, NULL((void *)0)}
326};
327
328static const struct token t_show_extcommunity[] = {
329 { EXTCOM_SUBTYPE, "bdc", NONE, t_show_ext_subtype},
330 { EXTCOM_SUBTYPE, "defgw", NONE, t_show_ext_subtype},
331 { EXTCOM_SUBTYPE, "esi-lab", NONE, t_show_ext_subtype},
332 { EXTCOM_SUBTYPE, "esi-rt", NONE, t_show_ext_subtype},
333 { EXTCOM_SUBTYPE, "l2vid", NONE, t_show_ext_subtype},
334 { EXTCOM_SUBTYPE, "mac-mob", NONE, t_show_ext_subtype},
335 { EXTCOM_SUBTYPE, "odi", NONE, t_show_ext_subtype},
336 { EXTCOM_SUBTYPE, "ort", NONE, t_show_ext_subtype},
337 { EXTCOM_SUBTYPE, "ori", NONE, t_show_ext_subtype},
338 { EXTCOM_SUBTYPE, "ovs", NONE, t_show_ext_subtype},
339 { EXTCOM_SUBTYPE, "rt", NONE, t_show_ext_subtype},
340 { EXTCOM_SUBTYPE, "soo", NONE, t_show_ext_subtype},
341 { EXTCOM_SUBTYPE, "srcas", NONE, t_show_ext_subtype},
342 { EXTCOM_SUBTYPE, "vrfri", NONE, t_show_ext_subtype},
343 { ENDTOKEN, "", NONE, NULL((void *)0)}
344};
345
346static const struct token t_show_ext_subtype[] = {
347 { EXTCOMMUNITY, "", NONE, t_show_rib},
348 { ENDTOKEN, "", NONE, NULL((void *)0)}
349};
350
351static const struct token t_show_largecommunity[] = {
352 { LARGE_COMMUNITY, "", NONE, t_show_rib},
353 { ENDTOKEN, "", NONE, NULL((void *)0)}
354};
355
356static const struct token t_network[] = {
357 { KEYWORD, "add", NETWORK_ADD, t_prefix},
358 { KEYWORD, "delete", NETWORK_REMOVE, t_prefix},
359 { KEYWORD, "flush", NETWORK_FLUSH, NULL((void *)0)},
360 { KEYWORD, "show", NETWORK_SHOW, t_network_show},
361 { KEYWORD, "mrt", NETWORK_MRT, t_show_mrt},
362 { KEYWORD, "bulk", NETWORK_BULK_ADD, t_set},
363 { ENDTOKEN, "", NONE, NULL((void *)0)}
364};
365
366static const struct token t_prefix[] = {
367 { PREFIX, "", NONE, t_set},
368 { ENDTOKEN, "", NONE, NULL((void *)0)}
369};
370
371static const struct token t_network_show[] = {
372 { NOTOKEN, "", NONE, NULL((void *)0)},
373 { FAMILY, "", NONE, NULL((void *)0)},
374 { ENDTOKEN, "", NONE, NULL((void *)0)}
375};
376
377static const struct token t_rd[] = {
378 { RD, "", NONE, t_set},
379 { ENDTOKEN, "", NONE, NULL((void *)0)}
380};
381
382static const struct token t_set[] = {
383 { NOTOKEN, "", NONE, NULL((void *)0)},
384 { KEYWORD, "community", NONE, t_community},
385 { KEYWORD, "ext-community", NONE, t_extcommunity},
386 { KEYWORD, "large-community", NONE, t_largecommunity},
387 { KEYWORD, "localpref", NONE, t_localpref},
388 { KEYWORD, "med", NONE, t_med},
389 { KEYWORD, "metric", NONE, t_med},
390 { KEYWORD, "nexthop", NONE, t_nexthop},
391 { KEYWORD, "pftable", NONE, t_pftable},
392 { KEYWORD, "prepend-neighbor", NONE, t_prepnbr},
393 { KEYWORD, "prepend-self", NONE, t_prepself},
394 { KEYWORD, "rd", NONE, t_rd},
395 { KEYWORD, "weight", NONE, t_weight},
396 { KEYWORD, "add", NETWORK_BULK_ADD, NULL((void *)0)},
397 { KEYWORD, "delete", NETWORK_BULK_REMOVE, NULL((void *)0)},
398 { ENDTOKEN, "", NONE, NULL((void *)0)}
399};
400
401static const struct token t_community[] = {
402 { COMMUNITY, "", NONE, t_set},
403 { ENDTOKEN, "", NONE, NULL((void *)0)}
404};
405
406static const struct token t_extcommunity[] = {
407 { EXTCOM_SUBTYPE, "bdc", NONE, t_ext_subtype},
408 { EXTCOM_SUBTYPE, "defgw", NONE, t_ext_subtype},
409 { EXTCOM_SUBTYPE, "esi-lab", NONE, t_ext_subtype},
410 { EXTCOM_SUBTYPE, "esi-rt", NONE, t_ext_subtype},
411 { EXTCOM_SUBTYPE, "l2vid", NONE, t_ext_subtype},
412 { EXTCOM_SUBTYPE, "mac-mob", NONE, t_ext_subtype},
413 { EXTCOM_SUBTYPE, "odi", NONE, t_ext_subtype},
414 { EXTCOM_SUBTYPE, "ort", NONE, t_ext_subtype},
415 { EXTCOM_SUBTYPE, "ori", NONE, t_ext_subtype},
416 { EXTCOM_SUBTYPE, "ovs", NONE, t_ext_subtype},
417 { EXTCOM_SUBTYPE, "rt", NONE, t_ext_subtype},
418 { EXTCOM_SUBTYPE, "soo", NONE, t_ext_subtype},
419 { EXTCOM_SUBTYPE, "srcas", NONE, t_ext_subtype},
420 { EXTCOM_SUBTYPE, "vrfri", NONE, t_ext_subtype},
421 { ENDTOKEN, "", NONE, NULL((void *)0)}
422};
423
424static const struct token t_ext_subtype[] = {
425 { EXTCOMMUNITY, "", NONE, t_set},
426 { ENDTOKEN, "", NONE, NULL((void *)0)}
427};
428
429static const struct token t_largecommunity[] = {
430 { LARGE_COMMUNITY, "", NONE, t_set},
431 { ENDTOKEN, "", NONE, NULL((void *)0)}
432};
433
434static const struct token t_localpref[] = {
435 { LOCALPREF, "", NONE, t_set},
436 { ENDTOKEN, "", NONE, NULL((void *)0)}
437};
438
439static const struct token t_med[] = {
440 { MED, "", NONE, t_set},
441 { ENDTOKEN, "", NONE, NULL((void *)0)}
442};
443
444static const struct token t_nexthop[] = {
445 { NEXTHOP, "", NONE, t_set},
446 { ENDTOKEN, "", NONE, NULL((void *)0)}
447};
448
449static const struct token t_pftable[] = {
450 { PFTABLE, "", NONE, t_set},
451 { ENDTOKEN, "", NONE, NULL((void *)0)}
452};
453
454static const struct token t_prepnbr[] = {
455 { PREPNBR, "", NONE, t_set},
456 { ENDTOKEN, "", NONE, NULL((void *)0)}
457};
458
459static const struct token t_prepself[] = {
460 { PREPSELF, "", NONE, t_set},
461 { ENDTOKEN, "", NONE, NULL((void *)0)}
462};
463
464static const struct token t_weight[] = {
465 { WEIGHT, "", NONE, t_set},
466 { ENDTOKEN, "", NONE, NULL((void *)0)}
467};
468
469static const struct token t_log[] = {
470 { KEYWORD, "verbose", LOG_VERBOSE, NULL((void *)0)},
471 { KEYWORD, "brief", LOG_BRIEF, NULL((void *)0)},
472 { ENDTOKEN, "", NONE, NULL((void *)0)}
473};
474
475static const struct token t_fib_table[] = {
476 { RTABLE, "", NONE, t_fib},
477 { ENDTOKEN, "", NONE, NULL((void *)0)}
478};
479
480static const struct token t_show_fib_table[] = {
481 { RTABLE, "", NONE, t_show_fib},
482 { ENDTOKEN, "", NONE, NULL((void *)0)}
483};
484
485static const struct token t_show_rib_path[] = {
486 { PATHID, "", NONE, t_show_rib},
487 { ENDTOKEN, "", NONE, NULL((void *)0)}
488};
489
490static struct parse_result res;
491
492const struct token *match_token(int *argc, char **argv[],
493 const struct token []);
494void show_valid_args(const struct token []);
495
496int parse_addr(const char *, struct bgpd_addr *);
497int parse_asnum(const char *, size_t, u_int32_t *);
498int parse_number(const char *, struct parse_result *, enum token_type);
499void parsecommunity(struct community *c, int type, char *s);
500void parseextcommunity(struct community *c, const char *t, char *s);
501int parse_nexthop(const char *, struct parse_result *);
502
503struct parse_result *
504parse(int argc, char *argv[])
505{
506 const struct token *table = t_main;
507 const struct token *match;
508
509 bzero(&res, sizeof(res));
510 res.rtableid = getrtable();
511 TAILQ_INIT(&res.set)do { (&res.set)->tqh_first = ((void *)0); (&res.set
)->tqh_last = &(&res.set)->tqh_first; } while (
0)
;
512
513 while (argc >= 0) {
514 if ((match = match_token(&argc, &argv, table)) == NULL((void *)0)) {
515 fprintf(stderr(&__sF[2]), "valid commands/args:\n");
516 show_valid_args(table);
517 return (NULL((void *)0));
518 }
519
520 argc--;
521 argv++;
522
523 if (match->type == NOTOKEN || match->next == NULL((void *)0))
524 break;
525
526 table = match->next;
527 }
528
529 if (argc > 0) {
530 fprintf(stderr(&__sF[2]), "superfluous argument: %s\n", argv[0]);
531 return (NULL((void *)0));
532 }
533
534 return (&res);
535}
536
537const struct token *
538match_token(int *argc, char **argv[], const struct token table[])
539{
540 u_int i, match;
541 const struct token *t = NULL((void *)0);
542 struct filter_set *fs;
543 const char *word = *argv[0];
544 size_t wordlen = 0;
545
546 match = 0;
547 if (word != NULL((void *)0))
1
Assuming 'word' is not equal to NULL
2
Taking true branch
548 wordlen = strlen(word);
549 for (i = 0; table[i].type != ENDTOKEN; i++) {
3
Assuming field 'type' is not equal to ENDTOKEN
4
Loop condition is true. Entering loop body
550 switch (table[i].type) {
5
Control jumps to 'case RD:' at line 717
551 case NOTOKEN:
552 if (word == NULL((void *)0) || wordlen == 0) {
553 match++;
554 t = &table[i];
555 }
556 break;
557 case KEYWORD:
558 if (word != NULL((void *)0) && strncmp(word, table[i].keyword,
559 wordlen) == 0) {
560 match++;
561 t = &table[i];
562 if (t->value)
563 res.action = t->value;
564 }
565 break;
566 case FLAG:
567 if (word != NULL((void *)0) && strncmp(word, table[i].keyword,
568 wordlen) == 0) {
569 match++;
570 t = &table[i];
571 res.flags |= t->value;
572 }
573 break;
574 case FAMILY:
575 if (word == NULL((void *)0))
576 break;
577 if (!strcmp(word, "inet") ||
578 !strcasecmp(word, "IPv4")) {
579 match++;
580 t = &table[i];
581 res.aid = AID_INET1;
582 }
583 if (!strcmp(word, "inet6") ||
584 !strcasecmp(word, "IPv6")) {
585 match++;
586 t = &table[i];
587 res.aid = AID_INET62;
588 }
589 if (!strcasecmp(word, "VPNv4")) {
590 match++;
591 t = &table[i];
592 res.aid = AID_VPN_IPv43;
593 }
594 if (!strcasecmp(word, "VPNv6")) {
595 match++;
596 t = &table[i];
597 res.aid = AID_VPN_IPv64;
598 }
599 break;
600 case ADDRESS:
601 if (parse_addr(word, &res.addr)) {
602 match++;
603 t = &table[i];
604 }
605 break;
606 case PEERADDRESS:
607 if (parse_addr(word, &res.peeraddr)) {
608 match++;
609 t = &table[i];
610 }
611 break;
612 case PREFIX:
613 if (parse_prefix(word, wordlen, &res.addr, &res.prefixlen)) {
614 match++;
615 t = &table[i];
616 }
617 break;
618 case ASTYPE:
619 if (word != NULL((void *)0) && strncmp(word, table[i].keyword,
620 wordlen) == 0) {
621 match++;
622 t = &table[i];
623 res.as.type = t->value;
624 }
625 break;
626 case ASNUM:
627 if (parse_asnum(word, wordlen, &res.as.as_min)) {
628 res.as.as_max = res.as.as_min;
629 match++;
630 t = &table[i];
631 }
632 break;
633 case GROUPDESC:
634 res.is_group = 1;
635 /* FALLTHROUGH */
636 case PEERDESC:
637 if (!match && word != NULL((void *)0) && wordlen > 0) {
638 if (strlcpy(res.peerdesc, word,
639 sizeof(res.peerdesc)) >=
640 sizeof(res.peerdesc))
641 errx(1, "neighbor description too "
642 "long");
643 match++;
644 t = &table[i];
645 }
646 break;
647 case RIBNAME:
648 if (!match && word != NULL((void *)0) && wordlen > 0) {
649 if (strlcpy(res.rib, word, sizeof(res.rib)) >=
650 sizeof(res.rib))
651 errx(1, "rib name too long");
652 match++;
653 t = &table[i];
654 }
655 break;
656 case COMMUNICATION:
657 if (!match && word != NULL((void *)0) && wordlen > 0) {
658 if (strlcpy(res.reason, word,
659 sizeof(res.reason)) >=
660 sizeof(res.reason))
661 errx(1, "shutdown reason too long");
662 match++;
663 t = &table[i];
664 }
665 break;
666 case COMMUNITY:
667 case LARGE_COMMUNITY:
668 if (word != NULL((void *)0) && wordlen > 0) {
669 int type = COMMUNITY_TYPE_BASIC8;
670 char *p = strdup(word);
671
672 if (p == NULL((void *)0))
673 err(1, NULL((void *)0));
674 if (table[i].type == LARGE_COMMUNITY)
675 type = COMMUNITY_TYPE_LARGE32;
676 parsecommunity(&res.community, type, p);
677 free(p);
678
679 if ((fs = calloc(1, sizeof(*fs))) == NULL((void *)0))
680 err(1, NULL((void *)0));
681 fs->type = ACTION_SET_COMMUNITY;
682 fs->action.community = res.community;
683 TAILQ_INSERT_TAIL(&res.set, fs, entry)do { (fs)->entry.tqe_next = ((void *)0); (fs)->entry.tqe_prev
= (&res.set)->tqh_last; *(&res.set)->tqh_last =
(fs); (&res.set)->tqh_last = &(fs)->entry.tqe_next
; } while (0)
;
684
685 match++;
686 t = &table[i];
687 }
688 break;
689 case EXTCOM_SUBTYPE:
690 if (word != NULL((void *)0) && strncmp(word, table[i].keyword,
691 wordlen) == 0) {
692 res.ext_comm_subtype = table[i].keyword;
693 match++;
694 t = &table[i];
695 }
696 break;
697 case EXTCOMMUNITY:
698 if (word != NULL((void *)0) && wordlen > 0) {
699 char *p = strdup(word);
700
701 if (p == NULL((void *)0))
702 err(1, NULL((void *)0));
703 parseextcommunity(&res.community,
704 res.ext_comm_subtype, p);
705 free(p);
706
707 if ((fs = calloc(1, sizeof(*fs))) == NULL((void *)0))
708 err(1, NULL((void *)0));
709 fs->type = ACTION_SET_COMMUNITY;
710 fs->action.community = res.community;
711 TAILQ_INSERT_TAIL(&res.set, fs, entry)do { (fs)->entry.tqe_next = ((void *)0); (fs)->entry.tqe_prev
= (&res.set)->tqh_last; *(&res.set)->tqh_last =
(fs); (&res.set)->tqh_last = &(fs)->entry.tqe_next
; } while (0)
;
712
713 match++;
714 t = &table[i];
715 }
716 break;
717 case RD:
718 if (word
5.1
'word' is not equal to NULL
!= NULL((void *)0) && wordlen > 0) {
6
Assuming 'wordlen' is > 0
7
Taking true branch
719 char *p = strdup(word);
720 struct community ext;
721 u_int64_t rd;
722
723 if (p == NULL((void *)0))
8
Assuming 'p' is not equal to NULL
9
Taking false branch
724 err(1, NULL((void *)0));
725 parseextcommunity(&ext, "rt", p);
10
Calling 'parseextcommunity'
16
Returning from 'parseextcommunity'
726 free(p);
727
728 switch (ext.data3 >> 8) {
17
Control jumps to 'case 0:' at line 729
729 case EXT_COMMUNITY_TRANS_TWO_AS0x00:
730 rd = (0ULL << 48);
731 rd |= ((u_int64_t)ext.data1 & 0xffff)
18
The left operand of '&' is a garbage value
732 << 32;
733 rd |= (u_int64_t)ext.data2;
734 break;
735 case EXT_COMMUNITY_TRANS_IPV40x01:
736 rd = (1ULL << 48);
737 rd |= (u_int64_t)ext.data1 << 16;
738 rd |= (u_int64_t)ext.data2 & 0xffff;
739 break;
740 case EXT_COMMUNITY_TRANS_FOUR_AS0x02:
741 rd = (2ULL << 48);
742 rd |= (u_int64_t)ext.data1 << 16;
743 rd |= (u_int64_t)ext.data2 & 0xffff;
744 break;
745 default:
746 errx(1, "bad encoding of rd");
747 }
748 res.rd = htobe64(rd)(__uint64_t)(__builtin_constant_p(rd) ? (__uint64_t)((((__uint64_t
)(rd) & 0xff) << 56) | ((__uint64_t)(rd) & 0xff00ULL
) << 40 | ((__uint64_t)(rd) & 0xff0000ULL) <<
24 | ((__uint64_t)(rd) & 0xff000000ULL) << 8 | ((__uint64_t
)(rd) & 0xff00000000ULL) >> 8 | ((__uint64_t)(rd) &
0xff0000000000ULL) >> 24 | ((__uint64_t)(rd) & 0xff000000000000ULL
) >> 40 | ((__uint64_t)(rd) & 0xff00000000000000ULL
) >> 56) : __swap64md(rd))
;
749 match++;
750 t = &table[i];
751 }
752 break;
753 case LOCALPREF:
754 case MED:
755 case PREPNBR:
756 case PREPSELF:
757 case WEIGHT:
758 case RTABLE:
759 case PATHID:
760 if (word != NULL((void *)0) && wordlen > 0 &&
761 parse_number(word, &res, table[i].type)) {
762 match++;
763 t = &table[i];
764 }
765 break;
766 case NEXTHOP:
767 if (word != NULL((void *)0) && wordlen > 0 &&
768 parse_nexthop(word, &res)) {
769 match++;
770 t = &table[i];
771 }
772 break;
773 case PFTABLE:
774 if (word != NULL((void *)0) && wordlen > 0) {
775 if ((fs = calloc(1,
776 sizeof(struct filter_set))) == NULL((void *)0))
777 err(1, NULL((void *)0));
778 if (strlcpy(fs->action.pftable, word,
779 sizeof(fs->action.pftable)) >=
780 sizeof(fs->action.pftable))
781 errx(1, "pftable name too long");
782 TAILQ_INSERT_TAIL(&res.set, fs, entry)do { (fs)->entry.tqe_next = ((void *)0); (fs)->entry.tqe_prev
= (&res.set)->tqh_last; *(&res.set)->tqh_last =
(fs); (&res.set)->tqh_last = &(fs)->entry.tqe_next
; } while (0)
;
783 match++;
784 t = &table[i];
785 }
786 break;
787 case FILENAME:
788 if (word != NULL((void *)0) && wordlen > 0) {
789 if ((res.mrtfd = open(word, O_RDONLY0x0000)) == -1) {
790 /*
791 * ignore error if path has no / and
792 * does not exist. In hope to print
793 * usage.
794 */
795 if (errno(*__errno()) == ENOENT2 &&
796 !strchr(word, '/'))
797 break;
798 err(1, "mrt open(%s)", word);
799 }
800 match++;
801 t = &table[i];
802 }
803 break;
804 case ENDTOKEN:
805 break;
806 }
807 }
808
809 if (match != 1) {
810 if (word == NULL((void *)0))
811 fprintf(stderr(&__sF[2]), "missing argument:\n");
812 else if (match > 1)
813 fprintf(stderr(&__sF[2]), "ambiguous argument: %s\n", word);
814 else if (match < 1)
815 fprintf(stderr(&__sF[2]), "unknown argument: %s\n", word);
816 return (NULL((void *)0));
817 }
818
819 return (t);
820}
821
822void
823show_valid_args(const struct token table[])
824{
825 int i;
826
827 for (i = 0; table[i].type != ENDTOKEN; i++) {
828 switch (table[i].type) {
829 case NOTOKEN:
830 fprintf(stderr(&__sF[2]), " <cr>\n");
831 break;
832 case KEYWORD:
833 case FLAG:
834 case ASTYPE:
835 case EXTCOM_SUBTYPE:
836 fprintf(stderr(&__sF[2]), " %s\n", table[i].keyword);
837 break;
838 case ADDRESS:
839 case PEERADDRESS:
840 fprintf(stderr(&__sF[2]), " <address>\n");
841 break;
842 case PREFIX:
843 fprintf(stderr(&__sF[2]), " <address>[/<len>]\n");
844 break;
845 case ASNUM:
846 fprintf(stderr(&__sF[2]), " <asnum>\n");
847 break;
848 case GROUPDESC:
849 case PEERDESC:
850 fprintf(stderr(&__sF[2]), " <neighbor description>\n");
851 break;
852 case RIBNAME:
853 fprintf(stderr(&__sF[2]), " <rib name>\n");
854 break;
855 case COMMUNICATION:
856 fprintf(stderr(&__sF[2]), " <reason>\n");
857 break;
858 case COMMUNITY:
859 fprintf(stderr(&__sF[2]), " <community>\n");
860 break;
861 case LARGE_COMMUNITY:
862 fprintf(stderr(&__sF[2]), " <large-community>\n");
863 break;
864 case EXTCOMMUNITY:
865 fprintf(stderr(&__sF[2]), " <extended-community>\n");
866 break;
867 case RD:
868 fprintf(stderr(&__sF[2]), " <route-distinguisher>\n");
869 break;
870 case LOCALPREF:
871 case MED:
872 case PREPNBR:
873 case PREPSELF:
874 case WEIGHT:
875 case PATHID:
876 fprintf(stderr(&__sF[2]), " <number>\n");
877 break;
878 case RTABLE:
879 fprintf(stderr(&__sF[2]), " <rtableid>\n");
880 break;
881 case NEXTHOP:
882 fprintf(stderr(&__sF[2]), " <address>\n");
883 break;
884 case PFTABLE:
885 fprintf(stderr(&__sF[2]), " <pftable>\n");
886 break;
887 case FAMILY:
888 fprintf(stderr(&__sF[2]), " [ inet | inet6 | IPv4 | IPv6 | "
889 "VPNv4 | VPNv6 ]\n");
890 break;
891 case FILENAME:
892 fprintf(stderr(&__sF[2]), " <filename>\n");
893 break;
894 case ENDTOKEN:
895 break;
896 }
897 }
898}
899
900int
901parse_addr(const char *word, struct bgpd_addr *addr)
902{
903 struct in_addr ina;
904 struct addrinfo hints, *r;
905
906 if (word == NULL((void *)0))
907 return (0);
908
909 bzero(addr, sizeof(struct bgpd_addr));
910 bzero(&ina, sizeof(ina));
911
912 if (inet_net_pton(AF_INET2, word, &ina, sizeof(ina)) != -1) {
913 addr->aid = AID_INET1;
914 addr->v4ba.v4 = ina;
915 return (1);
916 }
917
918 bzero(&hints, sizeof(hints));
919 hints.ai_family = AF_INET624;
920 hints.ai_socktype = SOCK_DGRAM2; /*dummy*/
921 hints.ai_flags = AI_NUMERICHOST4;
922 if (getaddrinfo(word, "0", &hints, &r) == 0) {
923 sa2addr(r->ai_addr, addr, NULL((void *)0));
924 freeaddrinfo(r);
925 return (1);
926 }
927
928 return (0);
929}
930
931int
932parse_prefix(const char *word, size_t wordlen, struct bgpd_addr *addr, u_int8_t *prefixlen)
933{
934 char *p, *ps;
935 const char *errstr;
936 int mask = -1;
937
938 if (word == NULL((void *)0))
939 return (0);
940
941 bzero(addr, sizeof(struct bgpd_addr));
942
943 if ((p = strrchr(word, '/')) != NULL((void *)0)) {
944 size_t plen = strlen(p);
945 mask = strtonum(p + 1, 0, 128, &errstr);
946 if (errstr)
947 errx(1, "netmask %s", errstr);
948
949 if ((ps = malloc(wordlen - plen + 1)) == NULL((void *)0))
950 err(1, "parse_prefix: malloc");
951 strlcpy(ps, word, wordlen - plen + 1);
952
953 if (parse_addr(ps, addr) == 0) {
954 free(ps);
955 return (0);
956 }
957
958 free(ps);
959 } else
960 if (parse_addr(word, addr) == 0)
961 return (0);
962
963 switch (addr->aid) {
964 case AID_INET1:
965 if (mask == -1)
966 mask = 32;
967 if (mask > 32)
968 errx(1, "invalid netmask: too large");
969 addr->v4ba.v4.s_addr = addr->v4ba.v4.s_addr & htonl(prefixlen2mask(mask))(__uint32_t)(__builtin_constant_p(prefixlen2mask(mask)) ? (__uint32_t
)(((__uint32_t)(prefixlen2mask(mask)) & 0xff) << 24
| ((__uint32_t)(prefixlen2mask(mask)) & 0xff00) <<
8 | ((__uint32_t)(prefixlen2mask(mask)) & 0xff0000) >>
8 | ((__uint32_t)(prefixlen2mask(mask)) & 0xff000000) >>
24) : __swap32md(prefixlen2mask(mask)))
;
970 break;
971 case AID_INET62:
972 if (mask == -1)
973 mask = 128;
974 inet6applymask(&addr->v6ba.v6, &addr->v6ba.v6, mask);
975 break;
976 default:
977 return (0);
978 }
979
980 *prefixlen = mask;
981 return (1);
982}
983
984int
985parse_asnum(const char *word, size_t wordlen, u_int32_t *asnum)
986{
987 const char *errstr;
988 char *dot, *parseword;
989 u_int32_t uval, uvalh = 0;
990
991 if (word == NULL((void *)0))
992 return (0);
993
994 if (wordlen < 1 || word[0] < '0' || word[0] > '9')
995 return (0);
996
997 parseword = strdup(word);
998 if ((dot = strchr(parseword, '.')) != NULL((void *)0)) {
999 *dot++ = '\0';
1000 uvalh = strtonum(parseword, 0, USHRT_MAX(32767 *2 +1), &errstr);
1001 if (errstr)
1002 errx(1, "AS number is %s: %s", errstr, word);
1003 uval = strtonum(dot, 0, USHRT_MAX(32767 *2 +1), &errstr);
1004 if (errstr)
1005 errx(1, "AS number is %s: %s", errstr, word);
1006 } else {
1007 uval = strtonum(parseword, 0, UINT_MAX(2147483647 *2U +1U), &errstr);
1008 if (errstr)
1009 errx(1, "AS number is %s: %s", errstr, word);
1010 }
1011
1012 free(parseword);
1013 *asnum = uval | (uvalh << 16);
1014 return (1);
1015}
1016
1017int
1018parse_number(const char *word, struct parse_result *r, enum token_type type)
1019{
1020 struct filter_set *fs;
1021 const char *errstr;
1022 u_int uval;
1023
1024 if (word == NULL((void *)0))
1025 return (0);
1026
1027 uval = strtonum(word, 0, UINT_MAX(2147483647 *2U +1U), &errstr);
1028 if (errstr)
1029 errx(1, "number is %s: %s", errstr, word);
1030
1031 /* number was parseable */
1032 switch (type) {
1033 case RTABLE:
1034 r->rtableid = uval;
1035 return (1);
1036 case PATHID:
1037 r->pathid = uval;
1038 r->flags |= F_CTL_HAS_PATHID0x800000;
1039 return (1);
1040 default:
1041 break;
1042 }
1043
1044 if ((fs = calloc(1, sizeof(struct filter_set))) == NULL((void *)0))
1045 err(1, NULL((void *)0));
1046 switch (type) {
1047 case LOCALPREF:
1048 fs->type = ACTION_SET_LOCALPREF;
1049 fs->action.metric = uval;
1050 break;
1051 case MED:
1052 fs->type = ACTION_SET_MED;
1053 fs->action.metric = uval;
1054 break;
1055 case PREPNBR:
1056 if (uval > 128) {
1057 free(fs);
1058 return (0);
1059 }
1060 fs->type = ACTION_SET_PREPEND_PEER;
1061 fs->action.prepend = uval;
1062 break;
1063 case PREPSELF:
1064 if (uval > 128) {
1065 free(fs);
1066 return (0);
1067 }
1068 fs->type = ACTION_SET_PREPEND_SELF;
1069 fs->action.prepend = uval;
1070 break;
1071 case WEIGHT:
1072 fs->type = ACTION_SET_WEIGHT;
1073 fs->action.metric = uval;
1074 break;
1075 default:
1076 errx(1, "king bula sez bad things happen");
1077 }
1078
1079 TAILQ_INSERT_TAIL(&r->set, fs, entry)do { (fs)->entry.tqe_next = ((void *)0); (fs)->entry.tqe_prev
= (&r->set)->tqh_last; *(&r->set)->tqh_last
= (fs); (&r->set)->tqh_last = &(fs)->entry.
tqe_next; } while (0)
;
1080 return (1);
1081}
1082
1083static void
1084getcommunity(char *s, int large, u_int32_t *val, u_int32_t *flag)
1085{
1086 long long max = USHRT_MAX(32767 *2 +1);
1087 const char *errstr;
1088
1089 *flag = 0;
1090 *val = 0;
1091 if (strcmp(s, "*") == 0) {
1092 *flag = COMMUNITY_ANY1;
1093 return;
1094 } else if (strcmp(s, "neighbor-as") == 0) {
1095 *flag = COMMUNITY_NEIGHBOR_AS2;
1096 return;
1097 } else if (strcmp(s, "local-as") == 0) {
1098 *flag = COMMUNITY_LOCAL_AS3;
1099 return;
1100 }
1101 if (large)
1102 max = UINT_MAX(2147483647 *2U +1U);
1103 *val = strtonum(s, 0, max, &errstr);
1104 if (errstr)
1105 errx(1, "Community %s is %s (max: %llu)", s, errstr, max);
1106}
1107
1108static void
1109setcommunity(struct community *c, u_int32_t as, u_int32_t data,
1110 u_int32_t asflag, u_int32_t dataflag)
1111{
1112 c->flags = COMMUNITY_TYPE_BASIC8;
1113 c->flags |= asflag << 8;
1114 c->flags |= dataflag << 16;
1115 c->data1 = as;
1116 c->data2 = data;
1117 c->data3 = 0;
1118}
1119
1120static void
1121parselargecommunity(struct community *c, char *s)
1122{
1123 char *p, *q;
1124 u_int32_t dflag1, dflag2, dflag3;
1125
1126 if ((p = strchr(s, ':')) == NULL((void *)0))
1127 errx(1, "Bad community syntax");
1128 *p++ = 0;
1129
1130 if ((q = strchr(p, ':')) == NULL((void *)0))
1131 errx(1, "Bad community syntax");
1132 *q++ = 0;
1133
1134 getcommunity(s, 1, &c->data1, &dflag1);
1135 getcommunity(p, 1, &c->data2, &dflag2);
1136 getcommunity(q, 1, &c->data3, &dflag3);
1137
1138 c->flags = COMMUNITY_TYPE_LARGE32;
1139 c->flags |= dflag1 << 8;
1140 c->flags |= dflag2 << 16;
1141 c->flags |= dflag3 << 24;
1142}
1143
1144void
1145parsecommunity(struct community *c, int type, char *s)
1146{
1147 char *p;
1148 u_int32_t as, data, asflag, dataflag;
1149
1150 if (type == COMMUNITY_TYPE_LARGE32) {
1151 parselargecommunity(c, s);
1152 return;
1153 }
1154
1155 /* Well-known communities */
1156 if (strcasecmp(s, "GRACEFUL_SHUTDOWN") == 0) {
1157 setcommunity(c, COMMUNITY_WELLKNOWN0xffff,
1158 COMMUNITY_GRACEFUL_SHUTDOWN0x0000, 0, 0);
1159 return;
1160 } else if (strcasecmp(s, "NO_EXPORT") == 0) {
1161 setcommunity(c, COMMUNITY_WELLKNOWN0xffff,
1162 COMMUNITY_NO_EXPORT0xff01, 0, 0);
1163 return;
1164 } else if (strcasecmp(s, "NO_ADVERTISE") == 0) {
1165 setcommunity(c, COMMUNITY_WELLKNOWN0xffff,
1166 COMMUNITY_NO_ADVERTISE0xff02, 0, 0);
1167 return;
1168 } else if (strcasecmp(s, "NO_EXPORT_SUBCONFED") == 0) {
1169 setcommunity(c, COMMUNITY_WELLKNOWN0xffff,
1170 COMMUNITY_NO_EXPSUBCONFED0xff03, 0, 0);
1171 return;
1172 } else if (strcasecmp(s, "NO_PEER") == 0) {
1173 setcommunity(c, COMMUNITY_WELLKNOWN0xffff,
1174 COMMUNITY_NO_PEER0xff04, 0, 0);
1175 return;
1176 } else if (strcasecmp(s, "BLACKHOLE") == 0) {
1177 setcommunity(c, COMMUNITY_WELLKNOWN0xffff,
1178 COMMUNITY_BLACKHOLE0x029A, 0, 0);
1179 return;
1180 }
1181
1182 if ((p = strchr(s, ':')) == NULL((void *)0))
1183 errx(1, "Bad community syntax");
1184 *p++ = 0;
1185
1186 getcommunity(s, 0, &as, &asflag);
1187 getcommunity(p, 0, &data, &dataflag);
1188 setcommunity(c, as, data, asflag, dataflag);
1189}
1190
1191static int
1192parsesubtype(const char *name, int *type, int *subtype)
1193{
1194 const struct ext_comm_pairs *cp;
1195 int found = 0;
1196
1197 for (cp = iana_ext_comms; cp->subname != NULL((void *)0); cp++) {
1198 if (strcmp(name, cp->subname) == 0) {
1199 if (found == 0) {
1200 *type = cp->type;
1201 *subtype = cp->subtype;
1202 }
1203 found++;
1204 }
1205 }
1206 if (found > 1)
1207 *type = -1;
1208 return (found);
1209}
1210
1211static int
1212parseextvalue(int type, char *s, u_int32_t *v, u_int32_t *flag)
1213{
1214 const char *errstr;
1215 char *p;
1216 struct in_addr ip;
1217 u_int32_t uvalh, uval;
1218
1219 if (type != -1) {
1220 /* nothing */
1221 } else if (strcmp(s, "neighbor-as") == 0) {
1222 *flag = COMMUNITY_NEIGHBOR_AS2;
1223 *v = 0;
1224 return EXT_COMMUNITY_TRANS_FOUR_AS0x02;
1225 } else if (strcmp(s, "local-as") == 0) {
1226 *flag = COMMUNITY_LOCAL_AS3;
1227 *v = 0;
1228 return EXT_COMMUNITY_TRANS_FOUR_AS0x02;
1229 } else if ((p = strchr(s, '.')) == NULL((void *)0)) {
1230 /* AS_PLAIN number (4 or 2 byte) */
1231 strtonum(s, 0, USHRT_MAX(32767 *2 +1), &errstr);
1232 if (errstr == NULL((void *)0))
1233 type = EXT_COMMUNITY_TRANS_TWO_AS0x00;
1234 else
1235 type = EXT_COMMUNITY_TRANS_FOUR_AS0x02;
1236 } else if (strchr(p + 1, '.') == NULL((void *)0)) {
1237 /* AS_DOT number (4-byte) */
1238 type = EXT_COMMUNITY_TRANS_FOUR_AS0x02;
1239 } else {
1240 /* more than one dot -> IP address */
1241 type = EXT_COMMUNITY_TRANS_IPV40x01;
1242 }
1243
1244 switch (type) {
1245 case EXT_COMMUNITY_TRANS_TWO_AS0x00:
1246 uval = strtonum(s, 0, USHRT_MAX(32767 *2 +1), &errstr);
1247 if (errstr)
1248 errx(1, "Bad ext-community %s is %s", s, errstr);
1249 *v = uval;
1250 break;
1251 case EXT_COMMUNITY_TRANS_FOUR_AS0x02:
1252 if ((p = strchr(s, '.')) == NULL((void *)0)) {
1253 uval = strtonum(s, 0, UINT_MAX(2147483647 *2U +1U), &errstr);
1254 if (errstr)
1255 errx(1, "Bad ext-community %s is %s", s,
1256 errstr);
1257 *v = uval;
1258 break;
1259 }
1260 *p++ = '\0';
1261 uvalh = strtonum(s, 0, USHRT_MAX(32767 *2 +1), &errstr);
1262 if (errstr)
1263 errx(1, "Bad ext-community %s is %s", s, errstr);
1264 uval = strtonum(p, 0, USHRT_MAX(32767 *2 +1), &errstr);
1265 if (errstr)
1266 errx(1, "Bad ext-community %s is %s", p, errstr);
1267 *v = uval | (uvalh << 16);
1268 break;
1269 case EXT_COMMUNITY_TRANS_IPV40x01:
1270 if (inet_aton(s, &ip) == 0)
1271 errx(1, "Bad ext-community %s not parseable", s);
1272 *v = ntohl(ip.s_addr)(__uint32_t)(__builtin_constant_p(ip.s_addr) ? (__uint32_t)((
(__uint32_t)(ip.s_addr) & 0xff) << 24 | ((__uint32_t
)(ip.s_addr) & 0xff00) << 8 | ((__uint32_t)(ip.s_addr
) & 0xff0000) >> 8 | ((__uint32_t)(ip.s_addr) &
0xff000000) >> 24) : __swap32md(ip.s_addr))
;
1273 break;
1274 default:
1275 errx(1, "%s: unexpected type %d", __func__, type);
1276 }
1277 return (type);
1278}
1279
1280void
1281parseextcommunity(struct community *c, const char *t, char *s)
1282{
1283 const struct ext_comm_pairs *cp;
1284 char *p, *ep;
1285 u_int64_t ullval;
1286 u_int32_t uval, uval2, dflag1 = 0, dflag2 = 0;
1287 int type = 0, subtype = 0;
1288
1289 if (strcmp(t, "*") == 0 && strcmp(s, "*") == 0) {
1290 c->flags = COMMUNITY_TYPE_EXT16;
1291 c->flags |= COMMUNITY_ANY1 << 24;
1292 return;
1293 }
1294 if (parsesubtype(t, &type, &subtype) == 0)
11
Taking false branch
1295 errx(1, "Bad ext-community unknown type");
1296
1297 switch (type) {
12
'Default' branch taken. Execution continues on line 1360
1298 case EXT_COMMUNITY_TRANS_TWO_AS0x00:
1299 case EXT_COMMUNITY_TRANS_FOUR_AS0x02:
1300 case EXT_COMMUNITY_TRANS_IPV40x01:
1301 case -1:
1302 if (strcmp(s, "*") == 0) {
1303 dflag1 = COMMUNITY_ANY1;
1304 break;
1305 }
1306 if ((p = strchr(s, ':')) == NULL((void *)0))
1307 errx(1, "Bad ext-community %s", s);
1308 *p++ = '\0';
1309 type = parseextvalue(type, s, &uval, &dflag1);
1310
1311 switch (type) {
1312 case EXT_COMMUNITY_TRANS_TWO_AS0x00:
1313 getcommunity(p, 1, &uval2, &dflag2);
1314 break;
1315 case EXT_COMMUNITY_TRANS_IPV40x01:
1316 case EXT_COMMUNITY_TRANS_FOUR_AS0x02:
1317 getcommunity(p, 0, &uval2, &dflag2);
1318 break;
1319 default:
1320 errx(1, "parseextcommunity: unexpected result");
1321 }
1322
1323 c->data1 = uval;
1324 c->data2 = uval2;
1325 break;
1326 case EXT_COMMUNITY_TRANS_OPAQUE0x03:
1327 case EXT_COMMUNITY_TRANS_EVPN0x06:
1328 if (strcmp(s, "*") == 0) {
1329 dflag1 = COMMUNITY_ANY1;
1330 break;
1331 }
1332 errno(*__errno()) = 0;
1333 ullval = strtoull(s, &ep, 0);
1334 if (s[0] == '\0' || *ep != '\0')
1335 errx(1, "Bad ext-community bad value");
1336 if (errno(*__errno()) == ERANGE34 && ullval > EXT_COMMUNITY_OPAQUE_MAX0xffffffffffffULL)
1337 errx(1, "Bad ext-community value too big");
1338 c->data1 = ullval >> 32;
1339 c->data2 = ullval;
1340 break;
1341 case EXT_COMMUNITY_NON_TRANS_OPAQUE0x43:
1342 if (subtype == EXT_COMMUNITY_SUBTYPE_OVS0) {
1343 if (strcmp(s, "valid") == 0) {
1344 c->data2 = EXT_COMMUNITY_OVS_VALID0;
1345 break;
1346 } else if (strcmp(s, "invalid") == 0) {
1347 c->data2 = EXT_COMMUNITY_OVS_INVALID2;
1348 break;
1349 } else if (strcmp(s, "not-found") == 0) {
1350 c->data2 = EXT_COMMUNITY_OVS_NOTFOUND1;
1351 break;
1352 } else if (strcmp(s, "*") == 0) {
1353 dflag1 = COMMUNITY_ANY1;
1354 break;
1355 }
1356 }
1357 errx(1, "Bad ext-community %s", s);
1358 }
1359
1360 c->data3 = type << 8 | subtype;
1361
1362 /* special handling of ext-community rt * since type is not known */
1363 if (dflag1
12.1
'dflag1' is not equal to COMMUNITY_ANY
== COMMUNITY_ANY1 && type == -1) {
1364 c->flags = COMMUNITY_TYPE_EXT16;
1365 c->flags |= dflag1 << 8;
1366 return;
1367 }
1368
1369 /* verify type/subtype combo */
1370 for (cp = iana_ext_comms; cp->subname
12.2
Field 'subname' is not equal to NULL
!= NULL((void *)0); cp++) {
13
Loop condition is true. Entering loop body
1371 if (cp->type == type
13.1
'type' is equal to field 'type'
&& cp->subtype == subtype
13.2
'subtype' is equal to field 'subtype'
) {
14
Taking true branch
1372 c->flags = COMMUNITY_TYPE_EXT16;
1373 c->flags |= dflag1 << 8;
1374 c->flags |= dflag2 << 16;
1375 return;
15
Returning without writing to 'c->data1'
1376 }
1377 }
1378
1379 errx(1, "Bad ext-community bad format for type");
1380}
1381
1382int
1383parse_nexthop(const char *word, struct parse_result *r)
1384{
1385 struct filter_set *fs;
1386
1387 if ((fs = calloc(1, sizeof(struct filter_set))) == NULL((void *)0))
1388 err(1, NULL((void *)0));
1389
1390 if (strcmp(word, "blackhole") == 0)
1391 fs->type = ACTION_SET_NEXTHOP_BLACKHOLE;
1392 else if (strcmp(word, "reject") == 0)
1393 fs->type = ACTION_SET_NEXTHOP_REJECT;
1394 else if (strcmp(word, "no-modify") == 0)
1395 fs->type = ACTION_SET_NEXTHOP_NOMODIFY;
1396 else if (parse_addr(word, &fs->action.nexthop)) {
1397 fs->type = ACTION_SET_NEXTHOP;
1398 } else {
1399 free(fs);
1400 return (0);
1401 }
1402
1403 TAILQ_INSERT_TAIL(&r->set, fs, entry)do { (fs)->entry.tqe_next = ((void *)0); (fs)->entry.tqe_prev
= (&r->set)->tqh_last; *(&r->set)->tqh_last
= (fs); (&r->set)->tqh_last = &(fs)->entry.
tqe_next; } while (0)
;
1404 return (1);
1405}