1 /* $OpenBSD: print-ospf.c,v 1.22 2020/01/24 22:46:37 procter Exp $ */ 2 3 /* 4 * Copyright (c) 1992, 1993, 1994, 1995, 1996, 1997 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that: (1) source code distributions 9 * retain the above copyright notice and this paragraph in its entirety, (2) 10 * distributions including binary code include the above copyright notice and 11 * this paragraph in its entirety in the documentation or other materials 12 * provided with the distribution, and (3) all advertising materials mentioning 13 * features or use of this software display the following acknowledgement: 14 * ``This product includes software developed by the University of California, 15 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 16 * the University nor the names of its contributors may be used to endorse 17 * or promote products derived from this software without specific prior 18 * written permission. 19 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 20 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 22 * 23 * OSPF support contributed by Jeffrey Honig (jch@mitchell.cit.cornell.edu) 24 */ 25 26 #include <sys/time.h> 27 #include <sys/socket.h> 28 29 #include <netinet/in.h> 30 #include <netinet/ip.h> 31 #include <netinet/ip_var.h> 32 33 #include <ctype.h> 34 #include <stdio.h> 35 #include <string.h> 36 37 #include "interface.h" 38 #include "addrtoname.h" 39 40 #include "ospf.h" 41 42 struct bits { 43 u_int32_t bit; 44 const char *str; 45 }; 46 47 static const struct bits ospf_option_bits[] = { 48 { OSPF_OPTION_T, "T" }, 49 { OSPF_OPTION_E, "E" }, 50 { OSPF_OPTION_MC, "MC" }, 51 { 0, NULL } 52 }; 53 54 static const struct bits ospf_rla_flag_bits[] = { 55 { RLA_FLAG_B, "B" }, 56 { RLA_FLAG_E, "E" }, 57 { RLA_FLAG_W1, "W1" }, 58 { RLA_FLAG_W2, "W2" }, 59 { 0, NULL } 60 }; 61 62 static struct tok type2str[] = { 63 { OSPF_TYPE_UMD, "umd" }, 64 { OSPF_TYPE_HELLO, "hello" }, 65 { OSPF_TYPE_DB, "dd" }, 66 { OSPF_TYPE_LSR, "ls_req" }, 67 { OSPF_TYPE_LSU, "ls_upd" }, 68 { OSPF_TYPE_LSA, "ls_ack" }, 69 { 0, NULL } 70 }; 71 72 static char tstr[] = " [|ospf]"; 73 74 /* Forwards */ 75 static inline void ospf_print_seqage(u_int32_t, time_t); 76 static inline void ospf_print_bits(const struct bits *, u_char); 77 static void ospf_print_ls_type(u_int, const struct in_addr *, 78 const struct in_addr *, const char *); 79 static int ospf_print_lshdr(const struct lsa_hdr *); 80 static int ospf_print_lsa(const struct lsa *); 81 static int ospf_decode_v2(const struct ospfhdr *, const u_char *); 82 83 static inline void 84 ospf_print_seqage(u_int32_t seq, time_t us) 85 { 86 time_t sec = us % 60; 87 time_t mins = (us / 60) % 60; 88 time_t hour = us / 3600; 89 90 printf(" S %X age ", seq); 91 if (hour) 92 printf("%u:%02u:%02u", 93 (u_int32_t) hour, (u_int32_t) mins, (u_int32_t) sec); 94 else if (mins) 95 printf("%u:%02u", (u_int32_t) mins, (u_int32_t) sec); 96 else 97 printf("%u", (u_int32_t) sec); 98 } 99 100 101 static inline void 102 ospf_print_bits(const struct bits *bp, u_char options) 103 { 104 char sep = ' '; 105 106 do { 107 if (options & bp->bit) { 108 printf("%c%s", sep, bp->str); 109 sep = '/'; 110 } 111 } while ((++bp)->bit); 112 } 113 114 static void 115 ospf_print_ls_type(u_int ls_type, const struct in_addr *ls_stateid, 116 const struct in_addr *ls_router, const char *fmt) 117 { 118 119 switch (ls_type) { 120 121 case LS_TYPE_ROUTER: 122 printf(" rtr %s", ipaddr_string(ls_router)); 123 break; 124 125 case LS_TYPE_NETWORK: 126 printf(" net dr %s if %s", 127 ipaddr_string(ls_router), 128 ipaddr_string(ls_stateid)); 129 break; 130 131 case LS_TYPE_SUM_IP: 132 printf(" sum %s abr %s", 133 ipaddr_string(ls_stateid), 134 ipaddr_string(ls_router)); 135 break; 136 137 case LS_TYPE_SUM_ABR: 138 printf(" abr %s rtr %s", 139 ipaddr_string(ls_router), 140 ipaddr_string(ls_stateid)); 141 break; 142 143 case LS_TYPE_ASE: 144 printf(" ase %s asbr %s", 145 ipaddr_string(ls_stateid), 146 ipaddr_string(ls_router)); 147 break; 148 149 case LS_TYPE_GROUP: 150 printf(" group %s rtr %s", 151 ipaddr_string(ls_stateid), 152 ipaddr_string(ls_router)); 153 break; 154 155 default: 156 putchar(' '); 157 printf(fmt, ls_type); 158 break; 159 } 160 } 161 162 static int 163 ospf_print_lshdr(const struct lsa_hdr *lshp) 164 { 165 166 TCHECK(lshp->ls_type); 167 printf(" {"); /* } (ctags) */ 168 169 TCHECK(lshp->ls_options); 170 ospf_print_bits(ospf_option_bits, lshp->ls_options); 171 TCHECK(lshp->ls_seq); 172 ospf_print_seqage(ntohl(lshp->ls_seq), ntohs(lshp->ls_age)); 173 ospf_print_ls_type(lshp->ls_type, &lshp->ls_stateid, &lshp->ls_router, 174 "ls_type %d"); 175 176 return (0); 177 trunc: 178 return (1); 179 } 180 181 182 /* 183 * Print a single link state advertisement. If truncated return 1, else 0. 184 */ 185 static int 186 ospf_print_lsa(const struct lsa *lsap) 187 { 188 const u_char *ls_end; 189 const struct rlalink *rlp; 190 const struct tos_metric *tosp; 191 const struct in_addr *ap; 192 const struct aslametric *almp; 193 const struct mcla *mcp; 194 const u_int32_t *lp; 195 int j, k; 196 197 if (ospf_print_lshdr(&lsap->ls_hdr)) 198 return (1); 199 TCHECK(lsap->ls_hdr.ls_length); 200 ls_end = (u_char *)lsap + ntohs(lsap->ls_hdr.ls_length); 201 switch (lsap->ls_hdr.ls_type) { 202 203 case LS_TYPE_ROUTER: 204 TCHECK(lsap->lsa_un.un_rla.rla_flags); 205 ospf_print_bits(ospf_rla_flag_bits, 206 lsap->lsa_un.un_rla.rla_flags); 207 208 TCHECK(lsap->lsa_un.un_rla.rla_count); 209 j = ntohs(lsap->lsa_un.un_rla.rla_count); 210 TCHECK(lsap->lsa_un.un_rla.rla_link); 211 rlp = lsap->lsa_un.un_rla.rla_link; 212 while (j--) { 213 TCHECK(*rlp); 214 printf(" {"); /* } (ctags) */ 215 switch (rlp->link_type) { 216 217 case RLA_TYPE_VIRTUAL: 218 printf(" virt"); 219 /* FALLTHROUGH */ 220 221 case RLA_TYPE_ROUTER: 222 printf(" nbrid %s if %s", 223 ipaddr_string(&rlp->link_id), 224 ipaddr_string(&rlp->link_data)); 225 break; 226 227 case RLA_TYPE_TRANSIT: 228 printf(" dr %s if %s", 229 ipaddr_string(&rlp->link_id), 230 ipaddr_string(&rlp->link_data)); 231 break; 232 233 case RLA_TYPE_STUB: 234 printf(" net %s mask %s", 235 ipaddr_string(&rlp->link_id), 236 ipaddr_string(&rlp->link_data)); 237 break; 238 239 default: 240 /* { (ctags) */ 241 printf(" ??RouterLinksType %d?? }", 242 rlp->link_type); 243 return (0); 244 } 245 printf(" tos 0 metric %d", ntohs(rlp->link_tos0metric)); 246 tosp = (struct tos_metric *) 247 ((sizeof rlp->link_tos0metric) + (u_char *) rlp); 248 for (k = 0; k < (int) rlp->link_toscount; ++k, ++tosp) { 249 TCHECK(*tosp); 250 printf(" tos %d metric %d", 251 tosp->tos_type, 252 ntohs(tosp->tos_metric)); 253 } 254 /* { (ctags) */ 255 printf(" }"); 256 rlp = (struct rlalink *)((u_char *)(rlp + 1) + 257 ((rlp->link_toscount) * sizeof(*tosp))); 258 } 259 break; 260 261 case LS_TYPE_NETWORK: 262 TCHECK(lsap->lsa_un.un_nla.nla_mask); 263 printf(" mask %s rtrs", 264 ipaddr_string(&lsap->lsa_un.un_nla.nla_mask)); 265 ap = lsap->lsa_un.un_nla.nla_router; 266 while ((u_char *)ap < ls_end) { 267 TCHECK(*ap); 268 printf(" %s", ipaddr_string(ap)); 269 ++ap; 270 } 271 break; 272 273 case LS_TYPE_SUM_IP: 274 TCHECK(lsap->lsa_un.un_nla.nla_mask); 275 printf(" mask %s", 276 ipaddr_string(&lsap->lsa_un.un_sla.sla_mask)); 277 /* FALLTHROUGH */ 278 279 case LS_TYPE_SUM_ABR: 280 TCHECK(lsap->lsa_un.un_sla.sla_tosmetric); 281 lp = lsap->lsa_un.un_sla.sla_tosmetric; 282 while ((u_char *)lp < ls_end) { 283 u_int32_t ul; 284 285 TCHECK(*lp); 286 ul = ntohl(*lp); 287 printf(" tos %d metric %d", 288 (ul & SLA_MASK_TOS) >> SLA_SHIFT_TOS, 289 ul & SLA_MASK_METRIC); 290 ++lp; 291 } 292 break; 293 294 case LS_TYPE_ASE: 295 TCHECK(lsap->lsa_un.un_nla.nla_mask); 296 printf(" mask %s", 297 ipaddr_string(&lsap->lsa_un.un_asla.asla_mask)); 298 299 TCHECK(lsap->lsa_un.un_sla.sla_tosmetric); 300 almp = lsap->lsa_un.un_asla.asla_metric; 301 while ((u_char *)almp < ls_end) { 302 u_int32_t ul; 303 304 TCHECK(almp->asla_tosmetric); 305 ul = ntohl(almp->asla_tosmetric); 306 printf(" type %d tos %d metric %d", 307 (ul & ASLA_FLAG_EXTERNAL) ? 2 : 1, 308 (ul & ASLA_MASK_TOS) >> ASLA_SHIFT_TOS, 309 (ul & ASLA_MASK_METRIC)); 310 TCHECK(almp->asla_forward); 311 if (almp->asla_forward.s_addr) { 312 printf(" forward %s", 313 ipaddr_string(&almp->asla_forward)); 314 } 315 TCHECK(almp->asla_tag); 316 if (almp->asla_tag) { 317 printf(" tag %u", 318 ntohl(almp->asla_tag)); 319 } 320 ++almp; 321 } 322 break; 323 324 case LS_TYPE_GROUP: 325 /* Multicast extensions as of 23 July 1991 */ 326 mcp = lsap->lsa_un.un_mcla; 327 while ((u_char *)mcp < ls_end) { 328 TCHECK(mcp->mcla_vid); 329 switch (ntohl(mcp->mcla_vtype)) { 330 331 case MCLA_VERTEX_ROUTER: 332 printf(" rtr rtrid %s", 333 ipaddr_string(&mcp->mcla_vid)); 334 break; 335 336 case MCLA_VERTEX_NETWORK: 337 printf(" net dr %s", 338 ipaddr_string(&mcp->mcla_vid)); 339 break; 340 341 default: 342 printf(" ??VertexType %u??", 343 (u_int32_t)ntohl(mcp->mcla_vtype)); 344 break; 345 } 346 ++mcp; 347 } 348 } 349 350 /* { (ctags) */ 351 printf(" }"); 352 return (0); 353 trunc: 354 printf(" }"); 355 return (1); 356 } 357 358 static int 359 ospf_decode_v2(const struct ospfhdr *op, const u_char *dataend) 360 { 361 const struct in_addr *ap; 362 const struct lsr *lsrp; 363 const struct lsa_hdr *lshp; 364 const struct lsa *lsap; 365 char sep; 366 int i; 367 368 switch (op->ospf_type) { 369 370 case OSPF_TYPE_UMD: 371 /* 372 * Rob Coltun's special monitoring packets; 373 * do nothing 374 */ 375 break; 376 377 case OSPF_TYPE_HELLO: 378 if (vflag) { 379 TCHECK(op->ospf_hello.hello_deadint); 380 ospf_print_bits(ospf_option_bits, 381 op->ospf_hello.hello_options); 382 printf(" mask %s int %d pri %d dead %u", 383 ipaddr_string(&op->ospf_hello.hello_mask), 384 ntohs(op->ospf_hello.hello_helloint), 385 op->ospf_hello.hello_priority, 386 (u_int32_t)ntohl(op->ospf_hello.hello_deadint)); 387 } 388 TCHECK(op->ospf_hello.hello_dr); 389 if (op->ospf_hello.hello_dr.s_addr != 0) 390 printf(" dr %s", 391 ipaddr_string(&op->ospf_hello.hello_dr)); 392 TCHECK(op->ospf_hello.hello_bdr); 393 if (op->ospf_hello.hello_bdr.s_addr != 0) 394 printf(" bdr %s", 395 ipaddr_string(&op->ospf_hello.hello_bdr)); 396 if (vflag) { 397 printf(" nbrs"); 398 ap = op->ospf_hello.hello_neighbor; 399 while ((u_char *)ap < dataend) { 400 TCHECK(*ap); 401 printf(" %s", ipaddr_string(ap)); 402 ++ap; 403 } 404 } 405 break; /* HELLO */ 406 407 case OSPF_TYPE_DB: 408 TCHECK(op->ospf_db.db_options); 409 ospf_print_bits(ospf_option_bits, op->ospf_db.db_options); 410 sep = ' '; 411 TCHECK(op->ospf_db.db_flags); 412 if (op->ospf_db.db_flags & OSPF_DB_INIT) { 413 printf("%cI", sep); 414 sep = '/'; 415 } 416 if (op->ospf_db.db_flags & OSPF_DB_MORE) { 417 printf("%cM", sep); 418 sep = '/'; 419 } 420 if (op->ospf_db.db_flags & OSPF_DB_MASTER) { 421 printf("%cMS", sep); 422 sep = '/'; 423 } 424 TCHECK(op->ospf_db.db_seq); 425 printf(" mtu %u S %X", ntohs(op->ospf_db.db_mtu), 426 (u_int32_t)ntohl(op->ospf_db.db_seq)); 427 428 if (vflag) { 429 /* Print all the LS adv's */ 430 lshp = op->ospf_db.db_lshdr; 431 432 while (!ospf_print_lshdr(lshp)) { 433 /* { (ctags) */ 434 printf(" }"); 435 ++lshp; 436 } 437 } 438 break; 439 440 case OSPF_TYPE_LSR: 441 if (vflag) { 442 lsrp = op->ospf_lsr; 443 while ((u_char *)lsrp < dataend) { 444 TCHECK(*lsrp); 445 printf(" {"); /* } (ctags) */ 446 ospf_print_ls_type(ntohl(lsrp->ls_type), 447 &lsrp->ls_stateid, 448 &lsrp->ls_router, 449 "LinkStateType %d"); 450 /* { (ctags) */ 451 printf(" }"); 452 ++lsrp; 453 } 454 } 455 break; 456 457 case OSPF_TYPE_LSU: 458 if (vflag) { 459 lsap = op->ospf_lsu.lsu_lsa; 460 TCHECK(op->ospf_lsu.lsu_count); 461 i = ntohl(op->ospf_lsu.lsu_count); 462 while (i--) { 463 if (ospf_print_lsa(lsap)) 464 goto trunc; 465 lsap = (struct lsa *)((u_char *)lsap + 466 ntohs(lsap->ls_hdr.ls_length)); 467 } 468 } 469 break; 470 471 472 case OSPF_TYPE_LSA: 473 if (vflag) { 474 lshp = op->ospf_lsa.lsa_lshdr; 475 476 while (!ospf_print_lshdr(lshp)) { 477 /* { (ctags) */ 478 printf(" }"); 479 ++lshp; 480 } 481 } 482 break; 483 484 default: 485 printf("v2 type %d", op->ospf_type); 486 break; 487 } 488 return (0); 489 trunc: 490 return (1); 491 } 492 493 void 494 ospf_print(const u_char *bp, u_int length, const u_char *bp2) 495 { 496 const struct ospfhdr *op; 497 const struct ip *ip; 498 const u_char *dataend; 499 const char *cp; 500 501 op = (struct ospfhdr *)bp; 502 ip = (struct ip *)bp2; 503 /* Print the source and destination address */ 504 printf("%s > %s:", 505 ipaddr_string(&ip->ip_src), 506 ipaddr_string(&ip->ip_dst)); 507 508 /* XXX Before we do anything else, strip off the MD5 trailer */ 509 TCHECK(op->ospf_authtype); 510 if (ntohs(op->ospf_authtype) == OSPF_AUTH_MD5) { 511 length -= OSPF_AUTH_MD5_LEN; 512 snapend -= OSPF_AUTH_MD5_LEN; 513 } 514 515 /* If the type is valid translate it, or just print the type */ 516 /* value. If it's not valid, say so and return */ 517 TCHECK(op->ospf_type); 518 cp = tok2str(type2str, "type%d", op->ospf_type); 519 printf(" OSPFv%d-%s ", op->ospf_version, cp); 520 if (*cp == 't') 521 return; 522 523 TCHECK(op->ospf_len); 524 if (length < ntohs(op->ospf_len)) { 525 printf(" [len %d]", ntohs(op->ospf_len)); 526 return; 527 } else if (length > ntohs(op->ospf_len)) { 528 printf(" %d[%d]:", ntohs(op->ospf_len), length); 529 length = ntohs(op->ospf_len); 530 } else 531 printf(" %d:", length); 532 dataend = bp + length; 533 534 TCHECK(op->ospf_routerid); 535 printf(" rtrid %s", ipaddr_string(&op->ospf_routerid)); 536 537 TCHECK(op->ospf_areaid); 538 if (op->ospf_areaid.s_addr != 0) 539 printf(" area %s", ipaddr_string(&op->ospf_areaid)); 540 else 541 printf(" backbone"); 542 543 if (vflag) { 544 /* Print authentication data (should we really do this?) */ 545 TCHECK2(op->ospf_authdata[0], sizeof(op->ospf_authdata)); 546 switch (ntohs(op->ospf_authtype)) { 547 548 case OSPF_AUTH_NONE: 549 break; 550 551 case OSPF_AUTH_SIMPLE: 552 printf(" auth \""); 553 (void)fn_printn(op->ospf_authdata, 554 sizeof(op->ospf_authdata), NULL); 555 printf("\""); 556 break; 557 558 case OSPF_AUTH_MD5: { 559 struct ospf_md5_authdata auth; 560 memcpy(&auth, op->ospf_authdata, sizeof(auth)); 561 562 printf(" auth MD5 key-id %u", auth.auth_keyid); 563 if (vflag) 564 printf(" seq %u", ntohl(auth.auth_seq)); 565 if (vflag > 1) { 566 printf(" off %u len %u", 567 ntohs(auth.auth_md5_offset), 568 auth.auth_len); 569 } 570 break; 571 } 572 573 default: 574 printf(" ??authtype-%d??", ntohs(op->ospf_authtype)); 575 return; 576 } 577 } 578 /* Do rest according to version. */ 579 switch (op->ospf_version) { 580 581 case 2: 582 /* ospf version 2 */ 583 if (ospf_decode_v2(op, dataend)) 584 goto trunc; 585 break; 586 587 default: 588 printf(" ospf [version %d]", op->ospf_version); 589 break; 590 } /* end switch on version */ 591 592 return; 593 trunc: 594 printf("%s", tstr); 595 } 596