Bug Summary

File:src/usr.sbin/bgpctl/parser.c
Warning:line 1360, column 18
The result of the left shift is undefined because the left operand is negative

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'
726 free(p);
727
728 switch (ext.data3 >> 8) {
729 case EXT_COMMUNITY_TRANS_TWO_AS0x00:
730 rd = (0ULL << 48);
731 rd |= ((u_int64_t)ext.data1 & 0xffff)
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++) {
12
Assuming field 'subname' is not equal to NULL
13
Loop condition is true. Entering loop body
18
Assuming field 'subname' is equal to NULL
19
Loop condition is false. Execution continues on line 1206
1198 if (strcmp(name, cp->subname) == 0) {
14
Taking true branch
1199 if (found
14.1
'found' is equal to 0
== 0) {
15
Taking true branch
1200 *type = cp->type;
16
Value assigned to 'type', which participates in a condition later
17
Value assigned to 'type'
1201 *subtype = cp->subtype;
1202 }
1203 found++;
1204 }
1205 }
1206 if (found
19.1
'found' is <= 1
> 1)
20
Taking false branch
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
Calling 'parsesubtype'
21
Returning from 'parsesubtype'
22
Taking false branch
1295 errx(1, "Bad ext-community unknown type");
1296
1297 switch (type) {
23
Control jumps to 'case -1:' at line 1301
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) {
24
Taking true branch
1303 dflag1 = COMMUNITY_ANY1;
1304 break;
25
Execution continues on line 1360
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;
26
The result of the left shift is undefined because the left operand is negative
1361
1362 /* special handling of ext-community rt * since type is not known */
1363 if (dflag1 == 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 != NULL((void *)0); cp++) {
1371 if (cp->type == type && cp->subtype == subtype) {
1372 c->flags = COMMUNITY_TYPE_EXT16;
1373 c->flags |= dflag1 << 8;
1374 c->flags |= dflag2 << 16;
1375 return;
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}