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