1 /*
2 * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
3 * Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org>
4 * Copyright (c) 2003 Henning Brauer <henning@openbsd.org>
5 * Copyright (c) 2020 Richard Chivers <r.chivers@zengenti.com>
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20 #include <sys/types.h>
21 #include <sys/socket.h>
22 #include <sys/un.h>
23 #include <netinet/in.h>
24 #include <arpa/inet.h>
25 #include <net/if_media.h>
26 #include <net/if_types.h>
27
28 #include <err.h>
29 #include <errno.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <unistd.h>
34
35 #include "ospf.h"
36 #include "ospfd.h"
37 #include "ospfctl.h"
38 #include "ospfe.h"
39 #include "parser.h"
40
41 static void
show_head(struct parse_result * res)42 show_head(struct parse_result *res)
43 {
44 switch (res->action) {
45 case SHOW_IFACE:
46 printf("%-11s %-18s %-6s %-10s %-10s %-8s %3s %3s\n",
47 "Interface", "Address", "State", "HelloTimer", "Linkstate",
48 "Uptime", "nc", "ac");
49 break;
50 case SHOW_FIB:
51 printf("flags: * = valid, O = OSPF, C = Connected, "
52 "S = Static\n");
53 printf("%-6s %-4s %-20s %-17s\n", "Flags", "Prio",
54 "Destination", "Nexthop");
55 break;
56 case SHOW_FIB_IFACE:
57 printf("%-15s%-15s%s\n", "Interface", "Flags", "Link state");
58 break;
59 case SHOW_NBR:
60 printf("%-15s %-3s %-12s %-8s %-15s %-9s %s\n", "ID", "Pri",
61 "State", "DeadTime", "Address", "Iface","Uptime");
62 break;
63 case SHOW_RIB:
64 printf("%-20s %-17s %-12s %-9s %-7s %-8s\n", "Destination",
65 "Nexthop", "Path Type", "Type", "Cost", "Uptime");
66 break;
67 default:
68 break;
69 }
70 }
71
72 static void
show_summary(struct ctl_sum * sum)73 show_summary(struct ctl_sum *sum)
74 {
75 printf("Router ID: %s\n", inet_ntoa(sum->rtr_id));
76 printf("Uptime: %s\n", fmt_timeframe_core(sum->uptime));
77 printf("RFC1583 compatibility flag is ");
78 if (sum->rfc1583compat)
79 printf("enabled\n");
80 else
81 printf("disabled\n");
82
83 printf("SPF delay is %d msec(s), hold time between two SPFs "
84 "is %d msec(s)\n", sum->spf_delay, sum->spf_hold_time);
85 printf("Number of external LSA(s) %d (Checksum sum 0x%x)\n",
86 sum->num_ext_lsa, sum->ext_lsa_cksum);
87 printf("Number of areas attached to this router: %d\n",
88 sum->num_area);
89 }
90
91 static void
show_summary_area(struct ctl_sum_area * sumarea)92 show_summary_area(struct ctl_sum_area *sumarea)
93 {
94 printf("\nArea ID: %s\n", inet_ntoa(sumarea->area));
95 printf(" Number of interfaces in this area: %d\n",
96 sumarea->num_iface);
97 printf(" Number of fully adjacent neighbors in this "
98 "area: %d\n", sumarea->num_adj_nbr);
99 printf(" SPF algorithm executed %d time(s)\n",
100 sumarea->num_spf_calc);
101 printf(" Number LSA(s) %d (Checksum sum 0x%x)\n",
102 sumarea->num_lsa, sumarea->lsa_cksum);
103 }
104
105 static void
show_rib_head(struct in_addr aid,u_int8_t d_type,u_int8_t p_type)106 show_rib_head(struct in_addr aid, u_int8_t d_type, u_int8_t p_type)
107 {
108 char *header, *format, *format2;
109
110 switch (p_type) {
111 case PT_INTRA_AREA:
112 case PT_INTER_AREA:
113 switch (d_type) {
114 case DT_NET:
115 format = "Network Routing Table";
116 format2 = "";
117 break;
118 case DT_RTR:
119 format = "Router Routing Table";
120 format2 = "Type";
121 break;
122 default:
123 errx(1, "unknown route type");
124 }
125 break;
126 case PT_TYPE1_EXT:
127 case PT_TYPE2_EXT:
128 format = NULL;
129 format2 = "Cost 2";
130 if ((header = strdup("External Routing Table")) == NULL)
131 err(1, NULL);
132 break;
133 default:
134 errx(1, "unknown route type");
135 }
136
137 if (p_type != PT_TYPE1_EXT && p_type != PT_TYPE2_EXT)
138 if (asprintf(&header, "%s (Area %s)", format,
139 inet_ntoa(aid)) == -1)
140 err(1, NULL);
141
142 printf("\n%-18s %s\n", "", header);
143 free(header);
144
145 printf("\n%-18s %-15s %-15s %-12s %-7s %-7s\n", "Destination",
146 "Nexthop", "Adv Router", "Path type", "Cost", format2);
147 }
148
149 static void
show_interface(struct ctl_iface * iface,int detail)150 show_interface(struct ctl_iface *iface, int detail)
151 {
152 char *netid;
153
154 /* XXX This wasn't previously executed on detail call */
155 if (asprintf(&netid, "%s/%d", inet_ntoa(iface->addr),
156 mask2prefixlen(iface->mask.s_addr)) == -1)
157 err(1, NULL);
158
159 if (detail) {
160 printf("\n");
161 printf("Interface %s, line protocol is %s\n",
162 iface->name, print_link(iface->flags));
163 printf(" Internet address %s/%d, ",
164 inet_ntoa(iface->addr),
165 mask2prefixlen(iface->mask.s_addr));
166 printf("Area %s\n", inet_ntoa(iface->area));
167 printf(" Linkstate %s,",
168 get_linkstate(iface->if_type, iface->linkstate));
169 printf(" mtu %d\n", iface->mtu);
170 printf(" Router ID %s, network type %s, cost: %d\n",
171 inet_ntoa(iface->rtr_id),
172 if_type_name(iface->type), iface->metric);
173 if (iface->dependon[0] != '\0') {
174 printf(" Depends on %s, %s\n", iface->dependon,
175 iface->depend_ok ? "up" : "down");
176 }
177 printf(" Transmit delay is %d sec(s), state %s, priority %d\n",
178 iface->transmit_delay, if_state_name(iface->state),
179 iface->priority);
180 printf(" Designated Router (ID) %s, ",
181 inet_ntoa(iface->dr_id));
182 printf("interface address %s\n", inet_ntoa(iface->dr_addr));
183 printf(" Backup Designated Router (ID) %s, ",
184 inet_ntoa(iface->bdr_id));
185 printf("interface address %s\n", inet_ntoa(iface->bdr_addr));
186 if (iface->dead_interval == FAST_RTR_DEAD_TIME) {
187 printf(" Timer intervals configured, "
188 "hello %d msec, dead %d, wait %d, retransmit %d\n",
189 iface->fast_hello_interval, iface->dead_interval,
190 iface->dead_interval, iface->rxmt_interval);
191
192 } else {
193 printf(" Timer intervals configured, "
194 "hello %d, dead %d, wait %d, retransmit %d\n",
195 iface->hello_interval, iface->dead_interval,
196 iface->dead_interval, iface->rxmt_interval);
197 }
198
199 if (iface->passive)
200 printf(" Passive interface (No Hellos)\n");
201 else if (iface->hello_timer.tv_sec < 0)
202 printf(" Hello timer not running\n");
203 else
204 printf(" Hello timer due in %s+%ldmsec\n",
205 fmt_timeframe_core(iface->hello_timer.tv_sec),
206 iface->hello_timer.tv_usec / 1000);
207 printf(" Uptime %s\n", fmt_timeframe_core(iface->uptime));
208 printf(" Neighbor count is %d, adjacent neighbor count is "
209 "%d\n", iface->nbr_cnt, iface->adj_cnt);
210
211 if (iface->auth_type > 0) {
212 switch (iface->auth_type) {
213 case AUTH_SIMPLE:
214 printf(" Simple password authentication "
215 "enabled\n");
216 break;
217 case AUTH_CRYPT:
218 printf(" Message digest authentication "
219 "enabled\n");
220 printf(" Primary key id is %d\n",
221 iface->auth_keyid);
222 break;
223 default:
224 break;
225 }
226 }
227 } else {
228 printf("%-11s %-18s %-6s %-10s %-10s %s %3d %3d\n",
229 iface->name, netid, if_state_name(iface->state),
230 iface->hello_timer.tv_sec < 0 ? "-" :
231 fmt_timeframe_core(iface->hello_timer.tv_sec),
232 get_linkstate(iface->if_type, iface->linkstate),
233 fmt_timeframe_core(iface->uptime),
234 iface->nbr_cnt, iface->adj_cnt);
235 }
236 free(netid);
237 }
238
239
240 static void
show_neighbor(struct ctl_nbr * nbr,int detail)241 show_neighbor(struct ctl_nbr *nbr, int detail)
242 {
243 char *state;
244
245 if (asprintf(&state, "%s/%s", nbr_state_name(nbr->nbr_state),
246 if_state_name(nbr->iface_state)) == -1)
247 err(1, NULL);
248
249 if (detail) {
250 printf("\nNeighbor %s, ", inet_ntoa(nbr->id));
251 printf("interface address %s\n", inet_ntoa(nbr->addr));
252 printf(" Area %s, interface %s\n", inet_ntoa(nbr->area),
253 nbr->name);
254 printf(" Neighbor priority is %d, "
255 "State is %s, %d state changes\n",
256 nbr->priority, nbr_state_name(nbr->nbr_state),
257 nbr->state_chng_cnt);
258 printf(" DR is %s, ", inet_ntoa(nbr->dr));
259 printf("BDR is %s\n", inet_ntoa(nbr->bdr));
260 printf(" Options %s\n", print_ospf_options(nbr->options));
261 printf(" Dead timer due in %s\n",
262 fmt_timeframe_core(nbr->dead_timer));
263 printf(" Uptime %s\n", fmt_timeframe_core(nbr->uptime));
264 printf(" Database Summary List %d\n", nbr->db_sum_lst_cnt);
265 printf(" Link State Request List %d\n", nbr->ls_req_lst_cnt);
266 printf(" Link State Retransmission List %d\n",
267 nbr->ls_retrans_lst_cnt);
268 } else {
269 printf("%-15s %-3d %-12s %-9s", inet_ntoa(nbr->id),
270 nbr->priority, state, fmt_timeframe_core(nbr->dead_timer));
271 printf("%-15s %-9s %s\n", inet_ntoa(nbr->addr), nbr->name,
272 nbr->uptime == 0 ? "-" : fmt_timeframe_core(nbr->uptime));
273 }
274 free(state);
275 }
276
277 static void
show_rib(struct ctl_rt * rt,int detail)278 show_rib(struct ctl_rt *rt, int detail)
279 {
280 char *dstnet;
281 static u_int8_t lasttype;
282
283 if (detail) {
284 switch (rt->p_type) {
285 case PT_INTRA_AREA:
286 case PT_INTER_AREA:
287 switch (rt->d_type) {
288 case DT_NET:
289 if (lasttype != RIB_NET)
290 show_rib_head(rt->area, rt->d_type,
291 rt->p_type);
292 if (asprintf(&dstnet, "%s/%d",
293 inet_ntoa(rt->prefix), rt->prefixlen) == -1)
294 err(1, NULL);
295 lasttype = RIB_NET;
296 break;
297 case DT_RTR:
298 if (lasttype != RIB_RTR)
299 show_rib_head(rt->area, rt->d_type,
300 rt->p_type);
301 if (asprintf(&dstnet, "%s",
302 inet_ntoa(rt->prefix)) == -1)
303 err(1, NULL);
304 lasttype = RIB_RTR;
305 break;
306 default:
307 errx(1, "unknown route type");
308 }
309 printf("%-18s %-15s ", dstnet, inet_ntoa(rt->nexthop));
310 printf("%-15s %-12s %-7d", inet_ntoa(rt->adv_rtr),
311 path_type_name(rt->p_type), rt->cost);
312 free(dstnet);
313
314 if (rt->d_type == DT_RTR)
315 printf(" %-7s", print_ospf_rtr_flags(rt->flags));
316
317 printf("\n");
318 break;
319 case PT_TYPE1_EXT:
320 case PT_TYPE2_EXT:
321 if (lasttype != RIB_EXT)
322 show_rib_head(rt->area, rt->d_type, rt->p_type);
323
324 if (asprintf(&dstnet, "%s/%d", inet_ntoa(rt->prefix),
325 rt->prefixlen) == -1)
326 err(1, NULL);
327
328 printf("%-18s %-15s ", dstnet, inet_ntoa(rt->nexthop));
329 printf("%-15s %-12s %-7d %-7d\n", inet_ntoa(rt->adv_rtr),
330 path_type_name(rt->p_type), rt->cost, rt->cost2);
331
332 free(dstnet);
333
334 lasttype = RIB_EXT;
335 break;
336 default:
337 errx(1, "unknown route type");
338 }
339 } else {
340 switch (rt->d_type) {
341 case DT_NET:
342 if (asprintf(&dstnet, "%s/%d", inet_ntoa(rt->prefix),
343 rt->prefixlen) == -1)
344 err(1, NULL);
345 break;
346 case DT_RTR:
347 if (asprintf(&dstnet, "%s",
348 inet_ntoa(rt->prefix)) == -1)
349 err(1, NULL);
350 break;
351 default:
352 errx(1, "Invalid route type");
353 }
354
355 printf("%-20s %-16s%s %-12s %-9s %-7d %s\n", dstnet,
356 inet_ntoa(rt->nexthop), rt->connected ? "C" : " ",
357 path_type_name(rt->p_type),
358 dst_type_name(rt->d_type), rt->cost,
359 rt->uptime == 0 ? "-" : fmt_timeframe_core(rt->uptime));
360
361 free(dstnet);
362 }
363 }
364
365 static void
show_fib(struct kroute * k)366 show_fib(struct kroute *k)
367 {
368 char *p;
369
370 if (k->flags & F_DOWN)
371 printf(" ");
372 else
373 printf("*");
374
375 if (!(k->flags & F_KERNEL))
376 printf("O");
377 else if (k->flags & F_CONNECTED)
378 printf("C");
379 else if (k->flags & F_STATIC)
380 printf("S");
381 else
382 printf(" ");
383
384 printf(" ");
385 printf("%4d ", k->priority);
386 if (asprintf(&p, "%s/%u", inet_ntoa(k->prefix), k->prefixlen) == -1)
387 err(1, NULL);
388
389 printf("%-20s ", p);
390 free(p);
391
392 if (k->nexthop.s_addr)
393 printf("%s", inet_ntoa(k->nexthop));
394 else if (k->flags & F_CONNECTED)
395 printf("link#%u", k->ifindex);
396
397 printf("\n");
398 }
399
400 static void
show_fib_interface(struct kif * k)401 show_fib_interface(struct kif *k)
402 {
403 uint64_t ifms_type;
404
405 printf("%-15s", k->ifname);
406 printf("%-15s", k->flags & IFF_UP ? "UP" : "");
407 ifms_type = get_ifms_type(k->if_type);
408 if (ifms_type)
409 printf("%s, ", get_media_descr(ifms_type));
410
411 printf("%s", get_linkstate(k->if_type, k->link_state));
412
413 if (k->link_state != LINK_STATE_DOWN && k->baudrate > 0) {
414 printf(", ");
415 printf("%s", print_baudrate(k->baudrate));
416 }
417 printf("\n");
418 }
419
420 static void
show_database_head(struct in_addr aid,char * ifname,u_int8_t type)421 show_database_head(struct in_addr aid, char *ifname, u_int8_t type)
422 {
423 char *header, *format;
424 int cleanup = 0;
425
426 switch (type) {
427 case LSA_TYPE_ROUTER:
428 format = "Router Link States";
429 break;
430 case LSA_TYPE_NETWORK:
431 format = "Net Link States";
432 break;
433 case LSA_TYPE_SUM_NETWORK:
434 format = "Summary Net Link States";
435 break;
436 case LSA_TYPE_SUM_ROUTER:
437 format = "Summary Router Link States";
438 break;
439 case LSA_TYPE_EXTERNAL:
440 format = NULL;
441 if ((header = strdup("Type-5 AS External Link States")) == NULL)
442 err(1, NULL);
443 break;
444 case LSA_TYPE_LINK_OPAQ:
445 format = "Type-9 Link Local Opaque Link States";
446 break;
447 case LSA_TYPE_AREA_OPAQ:
448 format = "Type-10 Area Local Opaque Link States";
449 break;
450 case LSA_TYPE_AS_OPAQ:
451 format = NULL;
452 if ((header = strdup("Type-11 AS Wide Opaque Link States")) ==
453 NULL)
454 err(1, NULL);
455 break;
456 default:
457 if (asprintf(&format, "LSA type %x", ntohs(type)) == -1)
458 err(1, NULL);
459 cleanup = 1;
460 break;
461 }
462 if (type == LSA_TYPE_LINK_OPAQ) {
463 if (asprintf(&header, "%s (Area %s Interface %s)", format,
464 inet_ntoa(aid), ifname) == -1)
465 err(1, NULL);
466 } else if (type != LSA_TYPE_EXTERNAL && type != LSA_TYPE_AS_OPAQ)
467 if (asprintf(&header, "%s (Area %s)", format,
468 inet_ntoa(aid)) == -1)
469 err(1, NULL);
470
471 printf("\n%-15s %s\n\n", "", header);
472 free(header);
473 if (cleanup)
474 free(format);
475 }
476
477 static void
show_db_hdr_msg_detail(struct lsa_hdr * lsa)478 show_db_hdr_msg_detail(struct lsa_hdr *lsa)
479 {
480 printf("LS age: %d\n", ntohs(lsa->age));
481 printf("Options: %s\n", print_ospf_options(lsa->opts));
482 printf("LS Type: %s\n", print_ls_type(lsa->type));
483
484 switch (lsa->type) {
485 case LSA_TYPE_ROUTER:
486 printf("Link State ID: %s\n", log_id(lsa->ls_id));
487 break;
488 case LSA_TYPE_NETWORK:
489 printf("Link State ID: %s (address of Designated Router)\n",
490 log_id(lsa->ls_id));
491 break;
492 case LSA_TYPE_SUM_NETWORK:
493 printf("Link State ID: %s (Network ID)\n", log_id(lsa->ls_id));
494 break;
495 case LSA_TYPE_SUM_ROUTER:
496 printf("Link State ID: %s (ASBR Router ID)\n",
497 log_id(lsa->ls_id));
498 break;
499 case LSA_TYPE_EXTERNAL:
500 printf("Link State ID: %s (External Network Number)\n",
501 log_id(lsa->ls_id));
502 break;
503 case LSA_TYPE_LINK_OPAQ:
504 case LSA_TYPE_AREA_OPAQ:
505 case LSA_TYPE_AS_OPAQ:
506 printf("Link State ID: %s Type %d ID %d\n", log_id(lsa->ls_id),
507 LSA_24_GETHI(ntohl(lsa->ls_id)),
508 LSA_24_GETLO(ntohl(lsa->ls_id)));
509 break;
510 }
511
512 printf("Advertising Router: %s\n", log_adv_rtr(lsa->adv_rtr));
513 printf("LS Seq Number: 0x%08x\n", ntohl(lsa->seq_num));
514 printf("Checksum: 0x%04x\n", ntohs(lsa->ls_chksum));
515 printf("Length: %d\n", ntohs(lsa->len));
516 }
517
518 static void
show_db_simple(struct lsa_hdr * lsa,struct in_addr area_id,u_int8_t lasttype,char * ifname)519 show_db_simple(struct lsa_hdr *lsa, struct in_addr area_id, u_int8_t lasttype,
520 char *ifname)
521 {
522 if (lsa->type != lasttype) {
523 show_database_head(area_id, ifname, lsa->type);
524 printf("%-15s %-15s %-4s %-10s %-8s\n", "Link ID",
525 "Adv Router", "Age", "Seq#", "Checksum");
526 }
527 printf("%-15s %-15s %-4d 0x%08x 0x%04x\n",
528 log_id(lsa->ls_id), log_adv_rtr(lsa->adv_rtr),
529 ntohs(lsa->age), ntohl(lsa->seq_num),
530 ntohs(lsa->ls_chksum));
531 }
532 static void
show_db(struct lsa * lsa,struct in_addr area_id,u_int8_t lasttype,char * ifname)533 show_db(struct lsa *lsa, struct in_addr area_id, u_int8_t lasttype,
534 char *ifname)
535 {
536 struct in_addr addr, data;
537 struct lsa_asext *asext;
538 struct lsa_rtr_link *rtr_link;
539 u_int16_t i, nlinks, off;
540
541 if (lsa->hdr.type != lasttype)
542 show_database_head(area_id, ifname, lsa->hdr.type);
543 show_db_hdr_msg_detail(&lsa->hdr);
544
545 switch (lsa->hdr.type) {
546 case LSA_TYPE_EXTERNAL:
547 addr.s_addr = lsa->data.asext.mask;
548 printf("Network Mask: %s\n", inet_ntoa(addr));
549
550 asext = (struct lsa_asext *)((char *)lsa + sizeof(lsa->hdr));
551
552 printf(" Metric type: ");
553 if (ntohl(lsa->data.asext.metric) & LSA_ASEXT_E_FLAG)
554 printf("2\n");
555 else
556 printf("1\n");
557 printf(" Metric: %d\n", ntohl(asext->metric) &
558 LSA_METRIC_MASK);
559 addr.s_addr = asext->fw_addr;
560 printf(" Forwarding Address: %s\n", inet_ntoa(addr));
561 printf(" External Route Tag: %d\n\n", ntohl(asext->ext_tag));
562 break;
563 case LSA_TYPE_NETWORK:
564 addr.s_addr = lsa->data.net.mask;
565 printf("Network Mask: %s\n", inet_ntoa(addr));
566
567 nlinks = (ntohs(lsa->hdr.len) - sizeof(struct lsa_hdr)
568 - sizeof(u_int32_t)) / sizeof(struct lsa_net_link);
569 off = sizeof(lsa->hdr) + sizeof(u_int32_t);
570 printf("Number of Routers: %d\n", nlinks);
571
572 for (i = 0; i < nlinks; i++) {
573 addr.s_addr = lsa->data.net.att_rtr[i];
574 printf(" Attached Router: %s\n", inet_ntoa(addr));
575 }
576
577 printf("\n");
578 break;
579 case LSA_TYPE_ROUTER:
580 printf("Flags: %s\n", print_ospf_flags(lsa->data.rtr.flags));
581 nlinks = ntohs(lsa->data.rtr.nlinks);
582 printf("Number of Links: %d\n\n", nlinks);
583
584 off = sizeof(lsa->hdr) + sizeof(struct lsa_rtr);
585
586 for (i = 0; i < nlinks; i++) {
587 rtr_link = (struct lsa_rtr_link *)((char *)lsa + off);
588
589 printf(" Link connected to: %s\n",
590 print_rtr_link_type(rtr_link->type));
591
592 addr.s_addr = rtr_link->id;
593 data.s_addr = rtr_link->data;
594
595 switch (rtr_link->type) {
596 case LINK_TYPE_POINTTOPOINT:
597 case LINK_TYPE_VIRTUAL:
598 printf(" Link ID (Neighbors Router ID): "
599 "%s\n", inet_ntoa(addr));
600 printf(" Link Data (Router Interface "
601 "address): %s\n", inet_ntoa(data));
602 break;
603 case LINK_TYPE_TRANSIT_NET:
604 printf(" Link ID (Designated Router "
605 "address): %s\n", inet_ntoa(addr));
606 printf(" Link Data (Router Interface "
607 "address): %s\n", inet_ntoa(data));
608 break;
609 case LINK_TYPE_STUB_NET:
610 printf(" Link ID (Network ID): %s\n",
611 inet_ntoa(addr));
612 printf(" Link Data (Network Mask): %s\n",
613 inet_ntoa(data));
614 break;
615 default:
616 printf(" Link ID (Unknown): %s\n",
617 inet_ntoa(addr));
618 printf(" Link Data (Unknown): %s\n",
619 inet_ntoa(data));
620 break;
621 }
622
623 printf(" Metric: %d\n\n", ntohs(rtr_link->metric));
624
625 off += sizeof(struct lsa_rtr_link) +
626 rtr_link->num_tos * sizeof(u_int32_t);
627 }
628 break;
629 case LSA_TYPE_SUM_ROUTER:
630 if (lsa->hdr.type != lasttype)
631 show_database_head(area_id, ifname, lsa->hdr.type);
632
633 show_db_hdr_msg_detail(&lsa->hdr);
634 addr.s_addr = lsa->data.sum.mask;
635 printf("Network Mask: %s\n", inet_ntoa(addr));
636 printf("Metric: %d\n\n", ntohl(lsa->data.sum.metric) &
637 LSA_METRIC_MASK);
638 break;
639 case LSA_TYPE_LINK_OPAQ:
640 case LSA_TYPE_AREA_OPAQ:
641 case LSA_TYPE_AS_OPAQ:
642 if (lsa->hdr.type != lasttype)
643 show_database_head(area_id, ifname, lsa->hdr.type);
644
645 show_db_hdr_msg_detail(&lsa->hdr);
646 break;
647 }
648 }
649
650 static void
show_tail(void)651 show_tail(void)
652 {
653 /* nothing */
654 }
655
656 const struct output show_output = {
657 .head = show_head,
658 .summary = show_summary,
659 .summary_area = show_summary_area,
660 .interface = show_interface,
661 .neighbor = show_neighbor,
662 .rib = show_rib,
663 .fib = show_fib,
664 .fib_interface = show_fib_interface,
665 .db = show_db,
666 .db_simple = show_db_simple,
667 .tail = show_tail
668 };
669