1 /* $OpenBSD: print-ospf.c,v 1.19 2015/01/16 06:40:21 deraadt 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(register u_int32_t seq, register time_t us) 84 { 85 register time_t sec = us % 60; 86 register time_t mins = (us / 60) % 60; 87 register 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(register const struct bits *bp, register u_char options) 102 { 103 register 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(register u_int ls_type, 115 register const struct in_addr *ls_stateid, 116 register const struct in_addr *ls_router, register 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(register 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(register const struct lsa *lsap) 187 { 188 register const u_char *ls_end; 189 register const struct rlalink *rlp; 190 register const struct tos_metric *tosp; 191 register const struct in_addr *ap; 192 register const struct aslametric *almp; 193 register const struct mcla *mcp; 194 register const u_int32_t *lp; 195 register 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 register 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 register 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 fputs(" }", stdout); 352 return (0); 353 trunc: 354 fputs(" }", stdout); 355 return (1); 356 } 357 358 static int 359 ospf_decode_v2(register const struct ospfhdr *op, 360 register const u_char *dataend) 361 { 362 register const struct in_addr *ap; 363 register const struct lsr *lsrp; 364 register const struct lsa_hdr *lshp; 365 register const struct lsa *lsap; 366 register char sep; 367 register int i; 368 369 switch (op->ospf_type) { 370 371 case OSPF_TYPE_UMD: 372 /* 373 * Rob Coltun's special monitoring packets; 374 * do nothing 375 */ 376 break; 377 378 case OSPF_TYPE_HELLO: 379 if (vflag) { 380 TCHECK(op->ospf_hello.hello_deadint); 381 ospf_print_bits(ospf_option_bits, 382 op->ospf_hello.hello_options); 383 printf(" mask %s int %d pri %d dead %u", 384 ipaddr_string(&op->ospf_hello.hello_mask), 385 ntohs(op->ospf_hello.hello_helloint), 386 op->ospf_hello.hello_priority, 387 (u_int32_t)ntohl(op->ospf_hello.hello_deadint)); 388 } 389 TCHECK(op->ospf_hello.hello_dr); 390 if (op->ospf_hello.hello_dr.s_addr != 0) 391 printf(" dr %s", 392 ipaddr_string(&op->ospf_hello.hello_dr)); 393 TCHECK(op->ospf_hello.hello_bdr); 394 if (op->ospf_hello.hello_bdr.s_addr != 0) 395 printf(" bdr %s", 396 ipaddr_string(&op->ospf_hello.hello_bdr)); 397 if (vflag) { 398 printf(" nbrs"); 399 ap = op->ospf_hello.hello_neighbor; 400 while ((u_char *)ap < dataend) { 401 TCHECK(*ap); 402 printf(" %s", ipaddr_string(ap)); 403 ++ap; 404 } 405 } 406 break; /* HELLO */ 407 408 case OSPF_TYPE_DB: 409 TCHECK(op->ospf_db.db_options); 410 ospf_print_bits(ospf_option_bits, op->ospf_db.db_options); 411 sep = ' '; 412 TCHECK(op->ospf_db.db_flags); 413 if (op->ospf_db.db_flags & OSPF_DB_INIT) { 414 printf("%cI", sep); 415 sep = '/'; 416 } 417 if (op->ospf_db.db_flags & OSPF_DB_MORE) { 418 printf("%cM", sep); 419 sep = '/'; 420 } 421 if (op->ospf_db.db_flags & OSPF_DB_MASTER) { 422 printf("%cMS", sep); 423 sep = '/'; 424 } 425 TCHECK(op->ospf_db.db_seq); 426 printf(" mtu %u S %X", ntohs(op->ospf_db.db_mtu), 427 (u_int32_t)ntohl(op->ospf_db.db_seq)); 428 429 if (vflag) { 430 /* Print all the LS adv's */ 431 lshp = op->ospf_db.db_lshdr; 432 433 while (!ospf_print_lshdr(lshp)) { 434 /* { (ctags) */ 435 printf(" }"); 436 ++lshp; 437 } 438 } 439 break; 440 441 case OSPF_TYPE_LSR: 442 if (vflag) { 443 lsrp = op->ospf_lsr; 444 while ((u_char *)lsrp < dataend) { 445 TCHECK(*lsrp); 446 printf(" {"); /* } (ctags) */ 447 ospf_print_ls_type(ntohl(lsrp->ls_type), 448 &lsrp->ls_stateid, 449 &lsrp->ls_router, 450 "LinkStateType %d"); 451 /* { (ctags) */ 452 printf(" }"); 453 ++lsrp; 454 } 455 } 456 break; 457 458 case OSPF_TYPE_LSU: 459 if (vflag) { 460 lsap = op->ospf_lsu.lsu_lsa; 461 TCHECK(op->ospf_lsu.lsu_count); 462 i = ntohl(op->ospf_lsu.lsu_count); 463 while (i--) { 464 if (ospf_print_lsa(lsap)) 465 goto trunc; 466 lsap = (struct lsa *)((u_char *)lsap + 467 ntohs(lsap->ls_hdr.ls_length)); 468 } 469 } 470 break; 471 472 473 case OSPF_TYPE_LSA: 474 if (vflag) { 475 lshp = op->ospf_lsa.lsa_lshdr; 476 477 while (!ospf_print_lshdr(lshp)) { 478 /* { (ctags) */ 479 printf(" }"); 480 ++lshp; 481 } 482 } 483 break; 484 485 default: 486 printf("v2 type %d", op->ospf_type); 487 break; 488 } 489 return (0); 490 trunc: 491 return (1); 492 } 493 494 void 495 ospf_print(register const u_char *bp, register u_int length, 496 register const u_char *bp2) 497 { 498 register const struct ospfhdr *op; 499 register const struct ip *ip; 500 register const u_char *dataend; 501 register const char *cp; 502 503 op = (struct ospfhdr *)bp; 504 ip = (struct ip *)bp2; 505 /* Print the source and destination address */ 506 (void) printf("%s > %s:", 507 ipaddr_string(&ip->ip_src), 508 ipaddr_string(&ip->ip_dst)); 509 510 /* XXX Before we do anything else, strip off the MD5 trailer */ 511 TCHECK(op->ospf_authtype); 512 if (ntohs(op->ospf_authtype) == OSPF_AUTH_MD5) { 513 length -= OSPF_AUTH_MD5_LEN; 514 snapend -= OSPF_AUTH_MD5_LEN; 515 } 516 517 /* If the type is valid translate it, or just print the type */ 518 /* value. If it's not valid, say so and return */ 519 TCHECK(op->ospf_type); 520 cp = tok2str(type2str, "type%d", op->ospf_type); 521 printf(" OSPFv%d-%s ", op->ospf_version, cp); 522 if (*cp == 't') 523 return; 524 525 TCHECK(op->ospf_len); 526 if (length < ntohs(op->ospf_len)) { 527 printf(" [len %d]", ntohs(op->ospf_len)); 528 return; 529 } else if (length > ntohs(op->ospf_len)) { 530 printf(" %d[%d]:", ntohs(op->ospf_len), length); 531 length = ntohs(op->ospf_len); 532 } else 533 printf(" %d:", length); 534 dataend = bp + length; 535 536 TCHECK(op->ospf_routerid); 537 printf(" rtrid %s", ipaddr_string(&op->ospf_routerid)); 538 539 TCHECK(op->ospf_areaid); 540 if (op->ospf_areaid.s_addr != 0) 541 printf(" area %s", ipaddr_string(&op->ospf_areaid)); 542 else 543 printf(" backbone"); 544 545 if (vflag) { 546 /* Print authentication data (should we really do this?) */ 547 TCHECK2(op->ospf_authdata[0], sizeof(op->ospf_authdata)); 548 switch (ntohs(op->ospf_authtype)) { 549 550 case OSPF_AUTH_NONE: 551 break; 552 553 case OSPF_AUTH_SIMPLE: 554 printf(" auth \""); 555 (void)fn_printn(op->ospf_authdata, 556 sizeof(op->ospf_authdata), NULL); 557 printf("\""); 558 break; 559 560 case OSPF_AUTH_MD5: 561 printf(" auth MD5"); 562 break; 563 564 default: 565 printf(" ??authtype-%d??", ntohs(op->ospf_authtype)); 566 return; 567 } 568 } 569 /* Do rest according to version. */ 570 switch (op->ospf_version) { 571 572 case 2: 573 /* ospf version 2 */ 574 if (ospf_decode_v2(op, dataend)) 575 goto trunc; 576 break; 577 578 default: 579 printf(" ospf [version %d]", op->ospf_version); 580 break; 581 } /* end switch on version */ 582 583 return; 584 trunc: 585 fputs(tstr, stdout); 586 } 587