1 |
|
|
/* $OpenBSD: printconf.c,v 1.106 2017/08/12 16:47:50 phessler 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, PROFITS OR MIND, WHETHER IN |
17 |
|
|
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT |
18 |
|
|
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
19 |
|
|
*/ |
20 |
|
|
|
21 |
|
|
#include <limits.h> |
22 |
|
|
#include <stdio.h> |
23 |
|
|
#include <stdlib.h> |
24 |
|
|
#include <string.h> |
25 |
|
|
|
26 |
|
|
#include "bgpd.h" |
27 |
|
|
#include "mrt.h" |
28 |
|
|
#include "session.h" |
29 |
|
|
#include "rde.h" |
30 |
|
|
#include "log.h" |
31 |
|
|
|
32 |
|
|
void print_op(enum comp_ops); |
33 |
|
|
void print_community(int, int); |
34 |
|
|
void print_largecommunity(int64_t, int64_t, int64_t); |
35 |
|
|
void print_extcommunity(struct filter_extcommunity *); |
36 |
|
|
void print_origin(u_int8_t); |
37 |
|
|
void print_set(struct filter_set_head *); |
38 |
|
|
void print_mainconf(struct bgpd_config *); |
39 |
|
|
void print_rdomain_targets(struct filter_set_head *, const char *); |
40 |
|
|
void print_rdomain(struct rdomain *); |
41 |
|
|
const char *print_af(u_int8_t); |
42 |
|
|
void print_network(struct network_config *, const char *); |
43 |
|
|
void print_peer(struct peer_config *, struct bgpd_config *, |
44 |
|
|
const char *); |
45 |
|
|
const char *print_auth_alg(u_int8_t); |
46 |
|
|
const char *print_enc_alg(u_int8_t); |
47 |
|
|
void print_announce(struct peer_config *, const char *); |
48 |
|
|
void print_as(struct filter_rule *); |
49 |
|
|
void print_rule(struct peer *, struct filter_rule *); |
50 |
|
|
const char *mrt_type(enum mrt_type); |
51 |
|
|
void print_mrt(struct bgpd_config *, u_int32_t, u_int32_t, |
52 |
|
|
const char *, const char *); |
53 |
|
|
void print_groups(struct bgpd_config *, struct peer *); |
54 |
|
|
int peer_compare(const void *, const void *); |
55 |
|
|
|
56 |
|
|
void |
57 |
|
|
print_op(enum comp_ops op) |
58 |
|
|
{ |
59 |
|
|
switch (op) { |
60 |
|
|
case OP_RANGE: |
61 |
|
|
printf("-"); |
62 |
|
|
break; |
63 |
|
|
case OP_XRANGE: |
64 |
|
|
printf("><"); |
65 |
|
|
break; |
66 |
|
|
case OP_EQ: |
67 |
|
|
printf("="); |
68 |
|
|
break; |
69 |
|
|
case OP_NE: |
70 |
|
|
printf("!="); |
71 |
|
|
break; |
72 |
|
|
case OP_LE: |
73 |
|
|
printf("<="); |
74 |
|
|
break; |
75 |
|
|
case OP_LT: |
76 |
|
|
printf("<"); |
77 |
|
|
break; |
78 |
|
|
case OP_GE: |
79 |
|
|
printf(">="); |
80 |
|
|
break; |
81 |
|
|
case OP_GT: |
82 |
|
|
printf(">"); |
83 |
|
|
break; |
84 |
|
|
default: |
85 |
|
|
printf("?"); |
86 |
|
|
break; |
87 |
|
|
} |
88 |
|
|
} |
89 |
|
|
|
90 |
|
|
void |
91 |
|
|
print_community(int as, int type) |
92 |
|
|
{ |
93 |
|
|
if (as == COMMUNITY_ANY) |
94 |
|
|
printf("*:"); |
95 |
|
|
else if (as == COMMUNITY_NEIGHBOR_AS) |
96 |
|
|
printf("neighbor-as:"); |
97 |
|
|
else if (as == COMMUNITY_LOCAL_AS) |
98 |
|
|
printf("local-as:"); |
99 |
|
|
else |
100 |
|
|
printf("%u:", (unsigned int)as); |
101 |
|
|
|
102 |
|
|
if (type == COMMUNITY_ANY) |
103 |
|
|
printf("* "); |
104 |
|
|
else if (type == COMMUNITY_NEIGHBOR_AS) |
105 |
|
|
printf("neighbor-as "); |
106 |
|
|
else if (type == COMMUNITY_LOCAL_AS) |
107 |
|
|
printf("local-as"); |
108 |
|
|
else |
109 |
|
|
printf("%d ", type); |
110 |
|
|
} |
111 |
|
|
|
112 |
|
|
void |
113 |
|
|
print_largecommunity(int64_t as, int64_t ld1, int64_t ld2) |
114 |
|
|
{ |
115 |
|
|
if (as == COMMUNITY_ANY) |
116 |
|
|
printf("*:"); |
117 |
|
|
else if (as == COMMUNITY_NEIGHBOR_AS) |
118 |
|
|
printf("neighbor-as:"); |
119 |
|
|
else if (as == COMMUNITY_LOCAL_AS) |
120 |
|
|
printf("local-as:"); |
121 |
|
|
else |
122 |
|
|
printf("%lld:", as); |
123 |
|
|
|
124 |
|
|
if (ld1 == COMMUNITY_ANY) |
125 |
|
|
printf("*:"); |
126 |
|
|
else if (ld1 == COMMUNITY_NEIGHBOR_AS) |
127 |
|
|
printf("neighbor-as:"); |
128 |
|
|
else if (ld1 == COMMUNITY_LOCAL_AS) |
129 |
|
|
printf("local-as:"); |
130 |
|
|
else |
131 |
|
|
printf("%lld:", ld1); |
132 |
|
|
|
133 |
|
|
if (ld2 == COMMUNITY_ANY) |
134 |
|
|
printf("* "); |
135 |
|
|
else if (ld2 == COMMUNITY_NEIGHBOR_AS) |
136 |
|
|
printf("neighbor-as "); |
137 |
|
|
else if (ld2 == COMMUNITY_LOCAL_AS) |
138 |
|
|
printf("local-as "); |
139 |
|
|
else |
140 |
|
|
printf("%lld ", ld2); |
141 |
|
|
|
142 |
|
|
} |
143 |
|
|
|
144 |
|
|
|
145 |
|
|
void |
146 |
|
|
print_extcommunity(struct filter_extcommunity *c) |
147 |
|
|
{ |
148 |
|
|
printf("%s ", log_ext_subtype(c->type, c->subtype)); |
149 |
|
|
|
150 |
|
|
switch (c->type) { |
151 |
|
|
case EXT_COMMUNITY_TRANS_TWO_AS: |
152 |
|
|
printf("%hu:%u ", c->data.ext_as.as, c->data.ext_as.val); |
153 |
|
|
break; |
154 |
|
|
case EXT_COMMUNITY_TRANS_IPV4: |
155 |
|
|
printf("%s:%u ", inet_ntoa(c->data.ext_ip.addr), |
156 |
|
|
c->data.ext_ip.val); |
157 |
|
|
break; |
158 |
|
|
case EXT_COMMUNITY_TRANS_FOUR_AS: |
159 |
|
|
printf("%s:%u ", log_as(c->data.ext_as4.as4), |
160 |
|
|
c->data.ext_as.val); |
161 |
|
|
break; |
162 |
|
|
case EXT_COMMUNITY_TRANS_OPAQUE: |
163 |
|
|
case EXT_COMMUNITY_TRANS_EVPN: |
164 |
|
|
printf("0x%llx ", c->data.ext_opaq); |
165 |
|
|
break; |
166 |
|
|
case EXT_COMMUNITY_NON_TRANS_OPAQUE: |
167 |
|
|
switch (c->data.ext_opaq) { |
168 |
|
|
case EXT_COMMUNITY_OVS_VALID: |
169 |
|
|
printf("valid "); |
170 |
|
|
break; |
171 |
|
|
case EXT_COMMUNITY_OVS_NOTFOUND: |
172 |
|
|
printf("not-found "); |
173 |
|
|
break; |
174 |
|
|
case EXT_COMMUNITY_OVS_INVALID: |
175 |
|
|
printf("invalid "); |
176 |
|
|
break; |
177 |
|
|
} |
178 |
|
|
break; |
179 |
|
|
default: |
180 |
|
|
printf("0x%llx ", c->data.ext_opaq); |
181 |
|
|
break; |
182 |
|
|
} |
183 |
|
|
} |
184 |
|
|
|
185 |
|
|
void |
186 |
|
|
print_origin(u_int8_t o) |
187 |
|
|
{ |
188 |
|
|
if (o == ORIGIN_IGP) |
189 |
|
|
printf("igp "); |
190 |
|
|
else if (o == ORIGIN_EGP) |
191 |
|
|
printf("egp "); |
192 |
|
|
else if (o == ORIGIN_INCOMPLETE) |
193 |
|
|
printf("incomplete "); |
194 |
|
|
else |
195 |
|
|
printf("%u ", o); |
196 |
|
|
} |
197 |
|
|
|
198 |
|
|
void |
199 |
|
|
print_set(struct filter_set_head *set) |
200 |
|
|
{ |
201 |
|
|
struct filter_set *s; |
202 |
|
|
|
203 |
|
|
if (TAILQ_EMPTY(set)) |
204 |
|
|
return; |
205 |
|
|
|
206 |
|
|
printf("set { "); |
207 |
|
|
TAILQ_FOREACH(s, set, entry) { |
208 |
|
|
switch (s->type) { |
209 |
|
|
case ACTION_SET_LOCALPREF: |
210 |
|
|
printf("localpref %u ", s->action.metric); |
211 |
|
|
break; |
212 |
|
|
case ACTION_SET_RELATIVE_LOCALPREF: |
213 |
|
|
printf("localpref %+d ", s->action.relative); |
214 |
|
|
break; |
215 |
|
|
case ACTION_SET_MED: |
216 |
|
|
printf("metric %u ", s->action.metric); |
217 |
|
|
break; |
218 |
|
|
case ACTION_SET_RELATIVE_MED: |
219 |
|
|
printf("metric %+d ", s->action.relative); |
220 |
|
|
break; |
221 |
|
|
case ACTION_SET_WEIGHT: |
222 |
|
|
printf("weight %u ", s->action.metric); |
223 |
|
|
break; |
224 |
|
|
case ACTION_SET_RELATIVE_WEIGHT: |
225 |
|
|
printf("weight %+d ", s->action.relative); |
226 |
|
|
break; |
227 |
|
|
case ACTION_SET_NEXTHOP: |
228 |
|
|
printf("nexthop %s ", log_addr(&s->action.nexthop)); |
229 |
|
|
break; |
230 |
|
|
case ACTION_SET_NEXTHOP_REJECT: |
231 |
|
|
printf("nexthop reject "); |
232 |
|
|
break; |
233 |
|
|
case ACTION_SET_NEXTHOP_BLACKHOLE: |
234 |
|
|
printf("nexthop blackhole "); |
235 |
|
|
break; |
236 |
|
|
case ACTION_SET_NEXTHOP_NOMODIFY: |
237 |
|
|
printf("nexthop no-modify "); |
238 |
|
|
break; |
239 |
|
|
case ACTION_SET_NEXTHOP_SELF: |
240 |
|
|
printf("nexthop self "); |
241 |
|
|
break; |
242 |
|
|
case ACTION_SET_PREPEND_SELF: |
243 |
|
|
printf("prepend-self %u ", s->action.prepend); |
244 |
|
|
break; |
245 |
|
|
case ACTION_SET_PREPEND_PEER: |
246 |
|
|
printf("prepend-neighbor %u ", s->action.prepend); |
247 |
|
|
break; |
248 |
|
|
case ACTION_DEL_COMMUNITY: |
249 |
|
|
printf("community delete "); |
250 |
|
|
print_community(s->action.community.as, |
251 |
|
|
s->action.community.type); |
252 |
|
|
printf(" "); |
253 |
|
|
break; |
254 |
|
|
case ACTION_SET_COMMUNITY: |
255 |
|
|
printf("community "); |
256 |
|
|
print_community(s->action.community.as, |
257 |
|
|
s->action.community.type); |
258 |
|
|
printf(" "); |
259 |
|
|
break; |
260 |
|
|
case ACTION_DEL_LARGE_COMMUNITY: |
261 |
|
|
printf("large-community delete "); |
262 |
|
|
print_largecommunity(s->action.large_community.as, |
263 |
|
|
s->action.large_community.ld1, |
264 |
|
|
s->action.large_community.ld2); |
265 |
|
|
printf(" "); |
266 |
|
|
break; |
267 |
|
|
case ACTION_SET_LARGE_COMMUNITY: |
268 |
|
|
printf("large-community "); |
269 |
|
|
print_largecommunity(s->action.large_community.as, |
270 |
|
|
s->action.large_community.ld1, |
271 |
|
|
s->action.large_community.ld2); |
272 |
|
|
printf(" "); |
273 |
|
|
break; |
274 |
|
|
case ACTION_PFTABLE: |
275 |
|
|
printf("pftable %s ", s->action.pftable); |
276 |
|
|
break; |
277 |
|
|
case ACTION_RTLABEL: |
278 |
|
|
printf("rtlabel %s ", s->action.rtlabel); |
279 |
|
|
break; |
280 |
|
|
case ACTION_SET_ORIGIN: |
281 |
|
|
printf("origin "); |
282 |
|
|
print_origin(s->action.origin); |
283 |
|
|
break; |
284 |
|
|
case ACTION_RTLABEL_ID: |
285 |
|
|
case ACTION_PFTABLE_ID: |
286 |
|
|
/* not possible */ |
287 |
|
|
printf("king bula saiz: config broken"); |
288 |
|
|
break; |
289 |
|
|
case ACTION_SET_EXT_COMMUNITY: |
290 |
|
|
printf("ext-community "); |
291 |
|
|
print_extcommunity(&s->action.ext_community); |
292 |
|
|
break; |
293 |
|
|
case ACTION_DEL_EXT_COMMUNITY: |
294 |
|
|
printf("ext-community delete "); |
295 |
|
|
print_extcommunity(&s->action.ext_community); |
296 |
|
|
break; |
297 |
|
|
} |
298 |
|
|
} |
299 |
|
|
printf("}"); |
300 |
|
|
} |
301 |
|
|
|
302 |
|
|
void |
303 |
|
|
print_mainconf(struct bgpd_config *conf) |
304 |
|
|
{ |
305 |
|
|
struct in_addr ina; |
306 |
|
|
struct listen_addr *la; |
307 |
|
|
|
308 |
|
|
printf("AS %s", log_as(conf->as)); |
309 |
|
|
if (conf->as > USHRT_MAX && conf->short_as != AS_TRANS) |
310 |
|
|
printf(" %u", conf->short_as); |
311 |
|
|
ina.s_addr = conf->bgpid; |
312 |
|
|
printf("\nrouter-id %s\n", inet_ntoa(ina)); |
313 |
|
|
|
314 |
|
|
printf("socket \"%s\"\n", conf->csock); |
315 |
|
|
if (conf->rcsock) |
316 |
|
|
printf("socket \"%s\" restricted\n", conf->rcsock); |
317 |
|
|
if (conf->holdtime) |
318 |
|
|
printf("holdtime %u\n", conf->holdtime); |
319 |
|
|
if (conf->min_holdtime) |
320 |
|
|
printf("holdtime min %u\n", conf->min_holdtime); |
321 |
|
|
if (conf->connectretry) |
322 |
|
|
printf("connect-retry %u\n", conf->connectretry); |
323 |
|
|
|
324 |
|
|
if (conf->flags & BGPD_FLAG_NO_EVALUATE) |
325 |
|
|
printf("route-collector yes\n"); |
326 |
|
|
|
327 |
|
|
if (conf->flags & BGPD_FLAG_DECISION_ROUTEAGE) |
328 |
|
|
printf("rde route-age evaluate\n"); |
329 |
|
|
|
330 |
|
|
if (conf->flags & BGPD_FLAG_DECISION_MED_ALWAYS) |
331 |
|
|
printf("rde med compare always\n"); |
332 |
|
|
|
333 |
|
|
if (conf->log & BGPD_LOG_UPDATES) |
334 |
|
|
printf("log updates\n"); |
335 |
|
|
|
336 |
|
|
TAILQ_FOREACH(la, conf->listen_addrs, entry) |
337 |
|
|
printf("listen on %s\n", |
338 |
|
|
log_sockaddr((struct sockaddr *)&la->sa)); |
339 |
|
|
|
340 |
|
|
if (conf->flags & BGPD_FLAG_NEXTHOP_BGP) |
341 |
|
|
printf("nexthop qualify via bgp\n"); |
342 |
|
|
if (conf->flags & BGPD_FLAG_NEXTHOP_DEFAULT) |
343 |
|
|
printf("nexthop qualify via default\n"); |
344 |
|
|
printf("fib-priority %hhu", conf->fib_priority); |
345 |
|
|
} |
346 |
|
|
|
347 |
|
|
void |
348 |
|
|
print_rdomain_targets(struct filter_set_head *set, const char *tgt) |
349 |
|
|
{ |
350 |
|
|
struct filter_set *s; |
351 |
|
|
TAILQ_FOREACH(s, set, entry) { |
352 |
|
|
printf("\t%s ", tgt); |
353 |
|
|
print_extcommunity(&s->action.ext_community); |
354 |
|
|
printf("\n"); |
355 |
|
|
} |
356 |
|
|
} |
357 |
|
|
|
358 |
|
|
void |
359 |
|
|
print_rdomain(struct rdomain *r) |
360 |
|
|
{ |
361 |
|
|
struct network *n; |
362 |
|
|
|
363 |
|
|
printf("rdomain %u {\n", r->rtableid); |
364 |
|
|
if (*r->descr) |
365 |
|
|
printf("\tdescr \"%s\"\n", r->descr); |
366 |
|
|
if (r->flags & F_RIB_NOFIBSYNC) |
367 |
|
|
printf("\tfib-update no\n"); |
368 |
|
|
else |
369 |
|
|
printf("\tfib-update yes\n"); |
370 |
|
|
printf("\tdepend on %s\n", r->ifmpe); |
371 |
|
|
|
372 |
|
|
TAILQ_FOREACH(n, &r->net_l, entry) |
373 |
|
|
print_network(&n->net, "\t"); |
374 |
|
|
|
375 |
|
|
printf("\n\t%s\n", log_rd(r->rd)); |
376 |
|
|
|
377 |
|
|
print_rdomain_targets(&r->export, "export-target"); |
378 |
|
|
print_rdomain_targets(&r->import, "import-target"); |
379 |
|
|
|
380 |
|
|
printf("}\n"); |
381 |
|
|
} |
382 |
|
|
|
383 |
|
|
const char * |
384 |
|
|
print_af(u_int8_t aid) |
385 |
|
|
{ |
386 |
|
|
/* |
387 |
|
|
* Hack around the fact that aid2str() will return "IPv4 unicast" |
388 |
|
|
* for AID_INET. AID_INET and AID_INET6 need special handling and |
389 |
|
|
* the other AID should never end up here (at least for now). |
390 |
|
|
*/ |
391 |
|
|
if (aid == AID_INET) |
392 |
|
|
return ("inet"); |
393 |
|
|
if (aid == AID_INET6) |
394 |
|
|
return ("inet6"); |
395 |
|
|
return (aid2str(aid)); |
396 |
|
|
} |
397 |
|
|
|
398 |
|
|
void |
399 |
|
|
print_network(struct network_config *n, const char *c) |
400 |
|
|
{ |
401 |
|
|
switch (n->type) { |
402 |
|
|
case NETWORK_STATIC: |
403 |
|
|
printf("%snetwork %s static", c, print_af(n->prefix.aid)); |
404 |
|
|
break; |
405 |
|
|
case NETWORK_CONNECTED: |
406 |
|
|
printf("%snetwork %s connected", c, print_af(n->prefix.aid)); |
407 |
|
|
break; |
408 |
|
|
case NETWORK_RTLABEL: |
409 |
|
|
printf("%snetwork %s rtlabel \"%s\"", c, |
410 |
|
|
print_af(n->prefix.aid), rtlabel_id2name(n->rtlabel)); |
411 |
|
|
break; |
412 |
|
|
default: |
413 |
|
|
printf("%snetwork %s/%u", c, log_addr(&n->prefix), |
414 |
|
|
n->prefixlen); |
415 |
|
|
break; |
416 |
|
|
} |
417 |
|
|
if (!TAILQ_EMPTY(&n->attrset)) |
418 |
|
|
printf(" "); |
419 |
|
|
print_set(&n->attrset); |
420 |
|
|
printf("\n"); |
421 |
|
|
} |
422 |
|
|
|
423 |
|
|
void |
424 |
|
|
print_peer(struct peer_config *p, struct bgpd_config *conf, const char *c) |
425 |
|
|
{ |
426 |
|
|
char *method; |
427 |
|
|
struct in_addr ina; |
428 |
|
|
|
429 |
|
|
if ((p->remote_addr.aid == AID_INET && p->remote_masklen != 32) || |
430 |
|
|
(p->remote_addr.aid == AID_INET6 && p->remote_masklen != 128)) |
431 |
|
|
printf("%sneighbor %s/%u {\n", c, log_addr(&p->remote_addr), |
432 |
|
|
p->remote_masklen); |
433 |
|
|
else |
434 |
|
|
printf("%sneighbor %s {\n", c, log_addr(&p->remote_addr)); |
435 |
|
|
if (p->descr[0]) |
436 |
|
|
printf("%s\tdescr \"%s\"\n", c, p->descr); |
437 |
|
|
if (p->rib[0]) |
438 |
|
|
printf("%s\trib \"%s\"\n", c, p->rib); |
439 |
|
|
if (p->remote_as) |
440 |
|
|
printf("%s\tremote-as %s\n", c, log_as(p->remote_as)); |
441 |
|
|
if (p->local_as != conf->as) { |
442 |
|
|
printf("%s\tlocal-as %s", c, log_as(p->local_as)); |
443 |
|
|
if (p->local_as > USHRT_MAX && p->local_short_as != AS_TRANS) |
444 |
|
|
printf(" %u", p->local_short_as); |
445 |
|
|
printf("\n"); |
446 |
|
|
} |
447 |
|
|
if (p->down) |
448 |
|
|
printf("%s\tdown\n", c); |
449 |
|
|
if (p->distance > 1) |
450 |
|
|
printf("%s\tmultihop %u\n", c, p->distance); |
451 |
|
|
if (p->passive) |
452 |
|
|
printf("%s\tpassive\n", c); |
453 |
|
|
if (p->local_addr.aid) |
454 |
|
|
printf("%s\tlocal-address %s\n", c, log_addr(&p->local_addr)); |
455 |
|
|
if (p->max_prefix) { |
456 |
|
|
printf("%s\tmax-prefix %u", c, p->max_prefix); |
457 |
|
|
if (p->max_prefix_restart) |
458 |
|
|
printf(" restart %u", p->max_prefix_restart); |
459 |
|
|
printf("\n"); |
460 |
|
|
} |
461 |
|
|
if (p->holdtime) |
462 |
|
|
printf("%s\tholdtime %u\n", c, p->holdtime); |
463 |
|
|
if (p->min_holdtime) |
464 |
|
|
printf("%s\tholdtime min %u\n", c, p->min_holdtime); |
465 |
|
|
if (p->announce_capa == 0) |
466 |
|
|
printf("%s\tannounce capabilities no\n", c); |
467 |
|
|
if (p->capabilities.refresh == 0) |
468 |
|
|
printf("%s\tannounce refresh no\n", c); |
469 |
|
|
if (p->capabilities.grestart.restart == 0) |
470 |
|
|
printf("%s\tannounce restart no\n", c); |
471 |
|
|
if (p->capabilities.as4byte == 0) |
472 |
|
|
printf("%s\tannounce as4byte no\n", c); |
473 |
|
|
if (p->announce_type == ANNOUNCE_SELF) |
474 |
|
|
printf("%s\tannounce self\n", c); |
475 |
|
|
else if (p->announce_type == ANNOUNCE_NONE) |
476 |
|
|
printf("%s\tannounce none\n", c); |
477 |
|
|
else if (p->announce_type == ANNOUNCE_ALL) |
478 |
|
|
printf("%s\tannounce all\n", c); |
479 |
|
|
else if (p->announce_type == ANNOUNCE_DEFAULT_ROUTE) |
480 |
|
|
printf("%s\tannounce default-route\n", c); |
481 |
|
|
else |
482 |
|
|
printf("%s\tannounce ???\n", c); |
483 |
|
|
if (p->enforce_as == ENFORCE_AS_ON) |
484 |
|
|
printf("%s\tenforce neighbor-as yes\n", c); |
485 |
|
|
else |
486 |
|
|
printf("%s\tenforce neighbor-as no\n", c); |
487 |
|
|
if (p->enforce_local_as == ENFORCE_AS_ON) |
488 |
|
|
printf("%s\tenforce local-as yes\n", c); |
489 |
|
|
else |
490 |
|
|
printf("%s\tenforce local-as no\n", c); |
491 |
|
|
if (p->reflector_client) { |
492 |
|
|
if (conf->clusterid == 0) |
493 |
|
|
printf("%s\troute-reflector\n", c); |
494 |
|
|
else { |
495 |
|
|
ina.s_addr = conf->clusterid; |
496 |
|
|
printf("%s\troute-reflector %s\n", c, |
497 |
|
|
inet_ntoa(ina)); |
498 |
|
|
} |
499 |
|
|
} |
500 |
|
|
if (p->demote_group[0]) |
501 |
|
|
printf("%s\tdemote %s\n", c, p->demote_group); |
502 |
|
|
if (p->if_depend[0]) |
503 |
|
|
printf("%s\tdepend on \"%s\"\n", c, p->if_depend); |
504 |
|
|
if (p->flags & PEERFLAG_TRANS_AS) |
505 |
|
|
printf("%s\ttransparent-as yes\n", c); |
506 |
|
|
|
507 |
|
|
if (p->flags & PEERFLAG_LOG_UPDATES) |
508 |
|
|
printf("%s\tlog updates\n", c); |
509 |
|
|
|
510 |
|
|
if (p->auth.method == AUTH_MD5SIG) |
511 |
|
|
printf("%s\ttcp md5sig\n", c); |
512 |
|
|
else if (p->auth.method == AUTH_IPSEC_MANUAL_ESP || |
513 |
|
|
p->auth.method == AUTH_IPSEC_MANUAL_AH) { |
514 |
|
|
if (p->auth.method == AUTH_IPSEC_MANUAL_ESP) |
515 |
|
|
method = "esp"; |
516 |
|
|
else |
517 |
|
|
method = "ah"; |
518 |
|
|
|
519 |
|
|
printf("%s\tipsec %s in spi %u %s XXXXXX", c, method, |
520 |
|
|
p->auth.spi_in, print_auth_alg(p->auth.auth_alg_in)); |
521 |
|
|
if (p->auth.enc_alg_in) |
522 |
|
|
printf(" %s XXXXXX", print_enc_alg(p->auth.enc_alg_in)); |
523 |
|
|
printf("\n"); |
524 |
|
|
|
525 |
|
|
printf("%s\tipsec %s out spi %u %s XXXXXX", c, method, |
526 |
|
|
p->auth.spi_out, print_auth_alg(p->auth.auth_alg_out)); |
527 |
|
|
if (p->auth.enc_alg_out) |
528 |
|
|
printf(" %s XXXXXX", |
529 |
|
|
print_enc_alg(p->auth.enc_alg_out)); |
530 |
|
|
printf("\n"); |
531 |
|
|
} else if (p->auth.method == AUTH_IPSEC_IKE_AH) |
532 |
|
|
printf("%s\tipsec ah ike\n", c); |
533 |
|
|
else if (p->auth.method == AUTH_IPSEC_IKE_ESP) |
534 |
|
|
printf("%s\tipsec esp ike\n", c); |
535 |
|
|
|
536 |
|
|
if (p->ttlsec) |
537 |
|
|
printf("%s\tttl-security yes\n", c); |
538 |
|
|
|
539 |
|
|
print_announce(p, c); |
540 |
|
|
|
541 |
|
|
print_mrt(conf, p->id, p->groupid, c, "\t"); |
542 |
|
|
|
543 |
|
|
printf("%s}\n", c); |
544 |
|
|
} |
545 |
|
|
|
546 |
|
|
const char * |
547 |
|
|
print_auth_alg(u_int8_t alg) |
548 |
|
|
{ |
549 |
|
|
switch (alg) { |
550 |
|
|
case SADB_AALG_SHA1HMAC: |
551 |
|
|
return ("sha1"); |
552 |
|
|
case SADB_AALG_MD5HMAC: |
553 |
|
|
return ("md5"); |
554 |
|
|
default: |
555 |
|
|
return ("???"); |
556 |
|
|
} |
557 |
|
|
} |
558 |
|
|
|
559 |
|
|
const char * |
560 |
|
|
print_enc_alg(u_int8_t alg) |
561 |
|
|
{ |
562 |
|
|
switch (alg) { |
563 |
|
|
case SADB_EALG_3DESCBC: |
564 |
|
|
return ("3des"); |
565 |
|
|
case SADB_X_EALG_AES: |
566 |
|
|
return ("aes"); |
567 |
|
|
default: |
568 |
|
|
return ("???"); |
569 |
|
|
} |
570 |
|
|
} |
571 |
|
|
|
572 |
|
|
void |
573 |
|
|
print_announce(struct peer_config *p, const char *c) |
574 |
|
|
{ |
575 |
|
|
u_int8_t aid; |
576 |
|
|
|
577 |
|
|
for (aid = 0; aid < AID_MAX; aid++) |
578 |
|
|
if (p->capabilities.mp[aid]) |
579 |
|
|
printf("%s\tannounce %s\n", c, aid2str(aid)); |
580 |
|
|
} |
581 |
|
|
|
582 |
|
|
void print_as(struct filter_rule *r) |
583 |
|
|
{ |
584 |
|
|
switch(r->match.as.op) { |
585 |
|
|
case OP_RANGE: |
586 |
|
|
printf("%s - ", log_as(r->match.as.as_min)); |
587 |
|
|
printf("%s ", log_as(r->match.as.as_max)); |
588 |
|
|
break; |
589 |
|
|
case OP_XRANGE: |
590 |
|
|
printf("%s >< ", log_as(r->match.as.as_min)); |
591 |
|
|
printf("%s ", log_as(r->match.as.as_max)); |
592 |
|
|
break; |
593 |
|
|
case OP_NE: |
594 |
|
|
printf("!= %s ", log_as(r->match.as.as)); |
595 |
|
|
break; |
596 |
|
|
default: |
597 |
|
|
printf("%s ", log_as(r->match.as.as)); |
598 |
|
|
break; |
599 |
|
|
} |
600 |
|
|
} |
601 |
|
|
|
602 |
|
|
void |
603 |
|
|
print_rule(struct peer *peer_l, struct filter_rule *r) |
604 |
|
|
{ |
605 |
|
|
struct peer *p; |
606 |
|
|
|
607 |
|
|
if (r->action == ACTION_ALLOW) |
608 |
|
|
printf("allow "); |
609 |
|
|
else if (r->action == ACTION_DENY) |
610 |
|
|
printf("deny "); |
611 |
|
|
else |
612 |
|
|
printf("match "); |
613 |
|
|
if (r->quick) |
614 |
|
|
printf("quick "); |
615 |
|
|
|
616 |
|
|
if (r->rib[0]) |
617 |
|
|
printf("rib %s ", r->rib); |
618 |
|
|
|
619 |
|
|
if (r->dir == DIR_IN) |
620 |
|
|
printf("from "); |
621 |
|
|
else if (r->dir == DIR_OUT) |
622 |
|
|
printf("to "); |
623 |
|
|
else |
624 |
|
|
printf("eeeeeeeps. "); |
625 |
|
|
|
626 |
|
|
if (r->peer.peerid) { |
627 |
|
|
for (p = peer_l; p != NULL && p->conf.id != r->peer.peerid; |
628 |
|
|
p = p->next) |
629 |
|
|
; /* nothing */ |
630 |
|
|
if (p == NULL) |
631 |
|
|
printf("? "); |
632 |
|
|
else |
633 |
|
|
printf("%s ", log_addr(&p->conf.remote_addr)); |
634 |
|
|
} else if (r->peer.groupid) { |
635 |
|
|
for (p = peer_l; p != NULL && |
636 |
|
|
p->conf.groupid != r->peer.groupid; p = p->next) |
637 |
|
|
; /* nothing */ |
638 |
|
|
if (p == NULL) |
639 |
|
|
printf("group ? "); |
640 |
|
|
else |
641 |
|
|
printf("group \"%s\" ", p->conf.group); |
642 |
|
|
} else if (r->peer.remote_as) { |
643 |
|
|
printf("AS %s ", log_as(r->peer.remote_as)); |
644 |
|
|
} else if (r->peer.ebgp) { |
645 |
|
|
printf("ebgp "); |
646 |
|
|
} else if (r->peer.ibgp) { |
647 |
|
|
printf("ibgp "); |
648 |
|
|
} else |
649 |
|
|
printf("any "); |
650 |
|
|
|
651 |
|
|
if (r->match.prefix.addr.aid) |
652 |
|
|
printf("prefix %s/%u ", log_addr(&r->match.prefix.addr), |
653 |
|
|
r->match.prefix.len); |
654 |
|
|
|
655 |
|
|
if (r->match.prefix.op) { |
656 |
|
|
if (r->match.prefix.op == OP_RANGE || |
657 |
|
|
r->match.prefix.op == OP_XRANGE) { |
658 |
|
|
printf("prefixlen %u ", r->match.prefix.len_min); |
659 |
|
|
print_op(r->match.prefix.op); |
660 |
|
|
printf(" %u ", r->match.prefix.len_max); |
661 |
|
|
} else { |
662 |
|
|
printf("prefixlen "); |
663 |
|
|
print_op(r->match.prefix.op); |
664 |
|
|
printf(" %u ", r->match.prefix.len_min); |
665 |
|
|
} |
666 |
|
|
} |
667 |
|
|
|
668 |
|
|
if (r->match.nexthop.flags) { |
669 |
|
|
if (r->match.nexthop.flags == FILTER_NEXTHOP_NEIGHBOR) |
670 |
|
|
printf("nexthop neighbor "); |
671 |
|
|
else |
672 |
|
|
printf("nexthop %s ", log_addr(&r->match.nexthop.addr)); |
673 |
|
|
} |
674 |
|
|
|
675 |
|
|
if (r->match.as.type) { |
676 |
|
|
if (r->match.as.type == AS_ALL) |
677 |
|
|
printf("AS "); |
678 |
|
|
else if (r->match.as.type == AS_SOURCE) |
679 |
|
|
printf("source-as "); |
680 |
|
|
else if (r->match.as.type == AS_TRANSIT) |
681 |
|
|
printf("transit-as "); |
682 |
|
|
else if (r->match.as.type == AS_PEER) |
683 |
|
|
printf("peer-as "); |
684 |
|
|
else |
685 |
|
|
printf("unfluffy-as "); |
686 |
|
|
print_as(r); |
687 |
|
|
} |
688 |
|
|
|
689 |
|
|
if (r->match.aslen.type) { |
690 |
|
|
printf("%s %u ", r->match.aslen.type == ASLEN_MAX ? |
691 |
|
|
"max-as-len" : "max-as-seq", r->match.aslen.aslen); |
692 |
|
|
} |
693 |
|
|
|
694 |
|
|
if (r->match.community.as != COMMUNITY_UNSET) { |
695 |
|
|
printf("community "); |
696 |
|
|
print_community(r->match.community.as, |
697 |
|
|
r->match.community.type); |
698 |
|
|
} |
699 |
|
|
if (r->match.ext_community.flags & EXT_COMMUNITY_FLAG_VALID) { |
700 |
|
|
printf("ext-community "); |
701 |
|
|
print_extcommunity(&r->match.ext_community); |
702 |
|
|
} |
703 |
|
|
if (r->match.large_community.as != COMMUNITY_UNSET) { |
704 |
|
|
printf("large-community "); |
705 |
|
|
print_largecommunity(r->match.large_community.as, |
706 |
|
|
r->match.large_community.ld1, |
707 |
|
|
r->match.large_community.ld2); |
708 |
|
|
} |
709 |
|
|
|
710 |
|
|
print_set(&r->set); |
711 |
|
|
|
712 |
|
|
printf("\n"); |
713 |
|
|
} |
714 |
|
|
|
715 |
|
|
const char * |
716 |
|
|
mrt_type(enum mrt_type t) |
717 |
|
|
{ |
718 |
|
|
switch (t) { |
719 |
|
|
case MRT_NONE: |
720 |
|
|
break; |
721 |
|
|
case MRT_TABLE_DUMP: |
722 |
|
|
return "table"; |
723 |
|
|
case MRT_TABLE_DUMP_MP: |
724 |
|
|
return "table-mp"; |
725 |
|
|
case MRT_TABLE_DUMP_V2: |
726 |
|
|
return "table-v2"; |
727 |
|
|
case MRT_ALL_IN: |
728 |
|
|
return "all in"; |
729 |
|
|
case MRT_ALL_OUT: |
730 |
|
|
return "all out"; |
731 |
|
|
case MRT_UPDATE_IN: |
732 |
|
|
return "updates in"; |
733 |
|
|
case MRT_UPDATE_OUT: |
734 |
|
|
return "updates out"; |
735 |
|
|
} |
736 |
|
|
return "unfluffy MRT"; |
737 |
|
|
} |
738 |
|
|
|
739 |
|
|
void |
740 |
|
|
print_mrt(struct bgpd_config *conf, u_int32_t pid, u_int32_t gid, |
741 |
|
|
const char *prep, const char *prep2) |
742 |
|
|
{ |
743 |
|
|
struct mrt *m; |
744 |
|
|
|
745 |
|
|
if (conf->mrt == NULL) |
746 |
|
|
return; |
747 |
|
|
|
748 |
|
|
LIST_FOREACH(m, conf->mrt, entry) |
749 |
|
|
if ((gid != 0 && m->group_id == gid) || |
750 |
|
|
(m->peer_id == pid && m->group_id == gid)) { |
751 |
|
|
printf("%s%sdump ", prep, prep2); |
752 |
|
|
if (m->rib[0]) |
753 |
|
|
printf("rib %s ", m->rib); |
754 |
|
|
printf("%s \"%s\"", mrt_type(m->type), |
755 |
|
|
MRT2MC(m)->name); |
756 |
|
|
if (MRT2MC(m)->ReopenTimerInterval == 0) |
757 |
|
|
printf("\n"); |
758 |
|
|
else |
759 |
|
|
printf(" %d\n", MRT2MC(m)->ReopenTimerInterval); |
760 |
|
|
} |
761 |
|
|
} |
762 |
|
|
|
763 |
|
|
void |
764 |
|
|
print_groups(struct bgpd_config *conf, struct peer *peer_l) |
765 |
|
|
{ |
766 |
|
|
struct peer_config **peerlist; |
767 |
|
|
struct peer *p; |
768 |
|
|
u_int peer_cnt, i; |
769 |
|
|
u_int32_t prev_groupid; |
770 |
|
|
const char *tab = "\t"; |
771 |
|
|
const char *nada = ""; |
772 |
|
|
const char *c; |
773 |
|
|
|
774 |
|
|
peer_cnt = 0; |
775 |
|
|
for (p = peer_l; p != NULL; p = p->next) |
776 |
|
|
peer_cnt++; |
777 |
|
|
|
778 |
|
|
if ((peerlist = calloc(peer_cnt, sizeof(struct peer_config *))) == NULL) |
779 |
|
|
fatal("print_groups calloc"); |
780 |
|
|
|
781 |
|
|
i = 0; |
782 |
|
|
for (p = peer_l; p != NULL; p = p->next) |
783 |
|
|
peerlist[i++] = &p->conf; |
784 |
|
|
|
785 |
|
|
qsort(peerlist, peer_cnt, sizeof(struct peer_config *), peer_compare); |
786 |
|
|
|
787 |
|
|
prev_groupid = 0; |
788 |
|
|
for (i = 0; i < peer_cnt; i++) { |
789 |
|
|
if (peerlist[i]->groupid) { |
790 |
|
|
c = tab; |
791 |
|
|
if (peerlist[i]->groupid != prev_groupid) { |
792 |
|
|
if (prev_groupid) |
793 |
|
|
printf("}\n\n"); |
794 |
|
|
printf("group \"%s\" {\n", peerlist[i]->group); |
795 |
|
|
prev_groupid = peerlist[i]->groupid; |
796 |
|
|
} |
797 |
|
|
} else |
798 |
|
|
c = nada; |
799 |
|
|
|
800 |
|
|
print_peer(peerlist[i], conf, c); |
801 |
|
|
} |
802 |
|
|
|
803 |
|
|
if (prev_groupid) |
804 |
|
|
printf("}\n\n"); |
805 |
|
|
|
806 |
|
|
free(peerlist); |
807 |
|
|
} |
808 |
|
|
|
809 |
|
|
int |
810 |
|
|
peer_compare(const void *aa, const void *bb) |
811 |
|
|
{ |
812 |
|
|
const struct peer_config * const *a; |
813 |
|
|
const struct peer_config * const *b; |
814 |
|
|
|
815 |
|
|
a = aa; |
816 |
|
|
b = bb; |
817 |
|
|
|
818 |
|
|
return ((*a)->groupid - (*b)->groupid); |
819 |
|
|
} |
820 |
|
|
|
821 |
|
|
void |
822 |
|
|
print_config(struct bgpd_config *conf, struct rib_names *rib_l, |
823 |
|
|
struct network_head *net_l, struct peer *peer_l, |
824 |
|
|
struct filter_head *rules_l, struct mrt_head *mrt_l, |
825 |
|
|
struct rdomain_head *rdom_l) |
826 |
|
|
{ |
827 |
|
|
struct filter_rule *r; |
828 |
|
|
struct network *n; |
829 |
|
|
struct rde_rib *rr; |
830 |
|
|
struct rdomain *rd; |
831 |
|
|
|
832 |
|
|
print_mainconf(conf); |
833 |
|
|
printf("\n"); |
834 |
|
|
TAILQ_FOREACH(n, net_l, entry) |
835 |
|
|
print_network(&n->net, ""); |
836 |
|
|
printf("\n"); |
837 |
|
|
SIMPLEQ_FOREACH(rd, rdom_l, entry) |
838 |
|
|
print_rdomain(rd); |
839 |
|
|
printf("\n"); |
840 |
|
|
SIMPLEQ_FOREACH(rr, rib_l, entry) { |
841 |
|
|
if (rr->flags & F_RIB_NOEVALUATE) |
842 |
|
|
printf("rde rib %s no evaluate\n", rr->name); |
843 |
|
|
else if (rr->flags & F_RIB_NOFIB) |
844 |
|
|
printf("rde rib %s\n", rr->name); |
845 |
|
|
else |
846 |
|
|
printf("rde rib %s rtable %u fib-update %s\n", rr->name, |
847 |
|
|
rr->rtableid, rr->flags & F_RIB_NOFIBSYNC ? |
848 |
|
|
"no" : "yes"); |
849 |
|
|
} |
850 |
|
|
printf("\n"); |
851 |
|
|
print_mrt(conf, 0, 0, "", ""); |
852 |
|
|
printf("\n"); |
853 |
|
|
print_groups(conf, peer_l); |
854 |
|
|
printf("\n"); |
855 |
|
|
TAILQ_FOREACH(r, rules_l, entry) |
856 |
|
|
print_rule(peer_l, r); |
857 |
|
|
} |