1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <stdio.h> 28 #include <fcntl.h> 29 #include <sys/socket.h> 30 #include <netinet/in.h> 31 #include <protocols/routed.h> 32 #include <string.h> 33 #include <arpa/inet.h> 34 #include "snoop.h" 35 #include "snoop_mip.h" 36 37 /* 38 * This defines the length of internal, unbounded buffers. We set 39 * this to be MAXLINE (the maximum verbose display line length) - 40 * 64, which should be enough for all necessary descriptions. 41 */ 42 #define BUFLEN MAXLINE - 64 43 44 extern char *dlc_header; 45 extern char *addrtoname(); 46 47 enum EXT_TYPE { ADV, REG }; 48 49 /* 50 * This defines the interface for all extention interpreter 51 * functions. The function will be called with following 52 * parameters: 53 * 54 * type: IN The type code for this extention 55 * len IN The length of the payload (i.e. the 56 * length field in an extension header) 57 * payload IN A pointer to the beginning of the 58 * extension payload 59 */ 60 typedef void interpreter_f(uint8_t type, uint8_t len, uchar_t *payload); 61 62 struct ext_dispatch { 63 uint8_t type; 64 interpreter_f *pfunc; 65 }; 66 67 /* Description structure -- maps type to description */ 68 struct ext_desc { 69 uint8_t type; 70 const char *desc; 71 }; 72 73 /* 74 * Interpreter function prototypes for both adv and reg. These 75 * all must implement the interpret_f interface defined above. 76 */ 77 static void spi_ext(uint8_t, uint8_t, uchar_t *); 78 static void key_ext(uint8_t, uint8_t, uchar_t *); 79 static void trav_ext(uint8_t, uint8_t, uchar_t *); 80 static void empty_ext(uint8_t, uint8_t, uchar_t *); 81 static void nai_ext(uint8_t, uint8_t, uchar_t *); 82 static void chall_ext(uint8_t, uint8_t, uchar_t *); 83 static void ma_ext(uint8_t, uint8_t, uchar_t *); 84 static void prefix_ext(uint8_t, uint8_t, uchar_t *); 85 static void unk_ext(uint8_t, uint8_t, uchar_t *); 86 87 /* R E G I S T R A T I O N */ 88 89 #define REG_TBL_LEN 10 /* update this when adding to the table */ 90 91 /* Reg: type to description mapping table */ 92 static struct ext_desc reg_desc[] = { 93 MN_HA_AUTH, "(Mobile-Home Authentication Extension)", 94 MN_FA_AUTH, "(Mobile-Foreign Authentication Extension", 95 FA_HA_AUTH, "(Foreign-Home Authentication Extension)", 96 GEN_AUTH, "(Generalized Authentication Extension)", 97 MN_HA_KEY, "(Mobile-Home Key Extension)", 98 MN_FA_KEY, "(Mobile-Foreign Key Extension)", 99 MN_HA_TRAVERSE, "(Firewall Traversal Extension)", 100 ENCAP_DELIV, "(Encapsulating Delivery Style Extension)", 101 MN_NAI, "(Mobile Node Network Access Identifier)", 102 FA_CHALLENGE, "(Mobile-Foreign Agent Challenge)", 103 0, "(Unrecognized Extension)" 104 }; 105 106 #define GENAUTH_TBL_LEN 1 /* update this when adding to the table */ 107 108 /* Subtypes for Generic Authentication Extension type (type 36) */ 109 static struct ext_desc genauth_desc[] = { 110 GEN_AUTH_MN_AAA, "(MN-AAA Authentication Subtype)", 111 0, "(Unrecognized Subtype)" 112 }; 113 114 /* Reg: type to function mapping table */ 115 static struct ext_dispatch reg_dispatch[] = { 116 MN_HA_AUTH, spi_ext, 117 MN_FA_AUTH, spi_ext, 118 FA_HA_AUTH, spi_ext, 119 GEN_AUTH, spi_ext, 120 MN_HA_KEY, key_ext, 121 MN_FA_KEY, key_ext, 122 MN_HA_TRAVERSE, trav_ext, 123 ENCAP_DELIV, empty_ext, 124 MN_NAI, nai_ext, 125 FA_CHALLENGE, chall_ext, 126 0, unk_ext 127 }; 128 129 /* A D V E R T I S E M E N T */ 130 131 #define ADV_TBL_LEN 5 /* update this when adding to the table */ 132 133 /* Adv: type to description mapping table */ 134 static struct ext_desc adv_desc[] = { 135 ICMP_ADV_MSG_PADDING_EXT, "(Padding)", 136 ICMP_ADV_MSG_MOBILITY_AGT_EXT, "(Mobility Agent Extension)", 137 ICMP_ADV_MSG_PREFIX_LENGTH_EXT, "(Prefix Lengths)", 138 ICMP_ADV_MSG_FA_CHALLENGE, "(Foreign Agent Challenge)", 139 ICMP_ADV_MSG_FA_NAI, "(Foreign Agent NAI)", 140 0, "(Unrecognized Extension)" 141 }; 142 143 /* Adv: type to function mapping table */ 144 static struct ext_dispatch adv_dispatch[] = { 145 ICMP_ADV_MSG_PADDING_EXT, NULL, /* never called */ 146 ICMP_ADV_MSG_MOBILITY_AGT_EXT, ma_ext, 147 ICMP_ADV_MSG_PREFIX_LENGTH_EXT, prefix_ext, 148 ICMP_ADV_MSG_FA_CHALLENGE, chall_ext, 149 ICMP_ADV_MSG_FA_NAI, nai_ext, 150 0, unk_ext 151 }; 152 153 #define GETSPI(payload, hi, low) \ 154 (void) memcpy(&hi, payload, sizeof (hi)); \ 155 (void) memcpy(&low, payload + sizeof (hi), sizeof (low)) 156 157 static void dumphex(uchar_t *payload, int payload_len, char *buf, char *msg) { 158 int index; 159 160 for (index = 0; index < payload_len; index++) { 161 (void) sprintf(&buf[index * 3], " %.2x", payload[index]); 162 } 163 164 (void) sprintf(get_line((char *)payload-dlc_header, 1), msg, buf); 165 } 166 167 static const char *get_desc(struct ext_desc table[], uint8_t type, int max) { 168 int i; 169 170 for (i = 0; i < max && table[i].type != type; i++) 171 /* NO_OP */; 172 173 return (table[i].desc); 174 } 175 176 /* 177 * The following is an accessor for the description table, used by 178 * snoop_icmp.c. This maintains the encapsulation of the internal 179 * description table. 180 */ 181 const char *get_mip_adv_desc(uint8_t type) { 182 return (get_desc(adv_desc, type, ADV_TBL_LEN)); 183 } 184 185 static interpreter_f *get_interpreter(struct ext_dispatch table[], 186 uint8_t type, 187 int max) { 188 int i; 189 190 for (i = 0; i < max && table[i].type != type; i++) 191 /* NO_OP */; 192 193 return (table[i].pfunc); 194 } 195 196 static int 197 interpret_extensions(uchar_t *ext, 198 int regext_size, 199 enum EXT_TYPE etype) { 200 201 int curr_size = regext_size; /* remaining total for all exts */ 202 exthdr_t *exthdr; 203 gen_exthdr_t *gen_exthdr; 204 const char *st; 205 uchar_t *p; 206 interpreter_f *f; 207 uint8_t ext_type; 208 uint16_t ext_len; 209 uint_t ext_hdrlen; 210 211 show_space(); 212 exthdr = (exthdr_t *)ALIGN(ext); 213 214 215 do { 216 ext_type = exthdr->type; 217 if (ext_type == GEN_AUTH) { 218 gen_exthdr = (gen_exthdr_t *)exthdr; 219 ext_hdrlen = sizeof (gen_exthdr_t); 220 ext_len = ntohs(gen_exthdr->length); 221 } else { 222 ext_hdrlen = sizeof (exthdr_t); 223 ext_len = exthdr->length; 224 } 225 226 if (!((etype == ADV && ext_type == ICMP_ADV_MSG_PADDING_EXT && 227 curr_size >= 1) || 228 curr_size >= ext_hdrlen + ext_len)) 229 break; 230 231 /* Print description for this extension */ 232 if (etype == ADV) { 233 st = get_desc(adv_desc, ext_type, ADV_TBL_LEN); 234 } else /* REG */ { 235 st = get_desc(reg_desc, ext_type, REG_TBL_LEN); 236 } 237 238 (void) sprintf(get_line((char *)exthdr-dlc_header, 1), 239 "Extension header type = %d %s", ext_type, st); 240 241 if (ext_type == GEN_AUTH) { 242 st = get_desc(genauth_desc, gen_exthdr->subtype, 243 GENAUTH_TBL_LEN); 244 (void) sprintf(get_line((char *)exthdr-dlc_header, 1), 245 "Subtype = %d %s", gen_exthdr->subtype, st); 246 } 247 248 /* Special case for 1-byte padding */ 249 if (etype == ADV && ext_type == ICMP_ADV_MSG_PADDING_EXT) { 250 exthdr = (exthdr_t *)((uchar_t *)exthdr + 1); 251 curr_size--; 252 continue; 253 } 254 255 (void) sprintf(get_line((char *)&exthdr->length-dlc_header, 1), 256 "Length = %d", ext_len); 257 258 /* Parse out the extension's payload */ 259 p = (uchar_t *)exthdr + ext_hdrlen; 260 curr_size -= (ext_hdrlen + ext_len); 261 262 if (etype == ADV) { 263 f = get_interpreter(adv_dispatch, ext_type, ADV_TBL_LEN); 264 } else /* REG */ { 265 f = get_interpreter(reg_dispatch, ext_type, REG_TBL_LEN); 266 } 267 268 f(ext_type, ext_len, p); 269 270 show_space(); 271 exthdr = (exthdr_t *)(p + ext_len); 272 } while (B_TRUE); 273 274 return (0); 275 } 276 277 void interpret_icmp_mip_ext(uchar_t *p, int len) { 278 show_space(); 279 show_header("ICMP: ", " MIP Advertisement Extensions ", len); 280 show_space(); 281 282 interpret_extensions(p, len, ADV); 283 } 284 285 void 286 interpret_mip_cntrlmsg(int flags, uchar_t *msg, int fraglen) { 287 char *pt, *pc = NULL; 288 char *line; 289 regreq_t rreq[1]; 290 regrep_t rrep[1]; 291 int regext_size; 292 uchar_t *regext_data; 293 struct in_addr addr_temp; 294 295 296 /* First byte of the message should be the type */ 297 switch (*msg) { 298 case REG_TYPE_REQ: 299 if (fraglen < sizeof (regreq_t)) 300 return; 301 pt = (flags & F_DTAIL ? "registration request ":"reg rqst "); 302 303 (void) memcpy(rreq, msg, sizeof (*rreq)); 304 regext_size = fraglen - sizeof (regreq_t); 305 regext_data = msg + sizeof (*rreq); 306 break; 307 case REG_TYPE_REP: 308 if (fraglen < sizeof (regrep_t)) 309 return; 310 pt = (flags & F_DTAIL ? "registration reply ":"reg reply "); 311 312 (void) memcpy(rrep, msg, sizeof (*rrep)); 313 regext_size = fraglen - sizeof (regrep_t); 314 regext_data = msg + sizeof (*rrep); 315 316 switch (rrep->code) { 317 case REPLY_CODE_ACK: 318 pc = ((flags & F_ALLSUM) || (flags & F_DTAIL)) ? 319 "OK" : "OK code 0"; 320 break; 321 case REPLY_CODE_ACK_NO_SIMULTANEOUS: 322 pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))? 323 "OK simultaneous bindings" : "OK code 1"; 324 break; 325 case REPLY_CODE_FA_NACK_UNSPECIFIED: 326 pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))? 327 "FA denial: unspecified":"FA denial: code 64"; 328 break; 329 case REPLY_CODE_FA_NACK_PROHIBITED: 330 pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))? 331 "FA denial: prohibited":"FA denial: code 65"; 332 break; 333 case REPLY_CODE_FA_NACK_RESOURCES: 334 pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))? 335 "FA denial: no resources":"FA denial: code 66"; 336 break; 337 case REPLY_CODE_FA_NACK_MN_AUTH: 338 pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))? 339 "FA denial: MN auth failed":"FA denial: code 67"; 340 break; 341 case REPLY_CODE_FA_NACK_HA_AUTH: 342 pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))? 343 "FA denial: HA auth failed": 344 "FA denial: code 68"; 345 break; 346 case REPLY_CODE_FA_NACK_LIFETIME: 347 pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))? 348 "FA denial: lifetime":"FA denial: code 69"; 349 break; 350 case REPLY_CODE_FA_NACK_BAD_REQUEST: 351 pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))? 352 "FA denial: bad request": "FA: code 70"; 353 break; 354 case REPLY_CODE_FA_NACK_BAD_REPLY: 355 pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))? 356 "FA denial: bad Reply":"FA denial: code 71"; 357 break; 358 case REPLY_CODE_FA_NACK_ENCAP_UNAVAILABLE: 359 pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))? 360 "FA denial: encapsulation":"FA denial: code 72"; 361 break; 362 case REPLY_CODE_FA_NACK_VJ_UNAVAILABLE: 363 pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))? 364 "FA denial: VJ compression":"FA denial: code 73"; 365 break; 366 case REPLY_CODE_FA_NACK_BIDIR_TUNNEL_UNAVAILABLE: 367 pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))? 368 "FA denial: reverse tunnel unavailable": 369 "FA denial: code 74"; 370 break; 371 case REPLY_CODE_FA_NACK_BIDIR_TUNNEL_NO_TBIT: 372 pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))? 373 "FA denial: reverse tunnel: missing T-bit": 374 "FA denial: code 75"; 375 break; 376 case REPLY_CODE_FA_NACK_BIDIR_TUNNEL_TOO_DISTANT: 377 pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))? 378 "FA denial: reverse tunnel: too distant": 379 "FA denial: code 76"; 380 break; 381 case REPLY_CODE_FA_NACK_ICMP_HA_NET_UNREACHABLE: 382 pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))? 383 "FA denial: home network unreachable": 384 "FA denial: code 80"; 385 break; 386 case REPLY_CODE_FA_NACK_ICMP_HA_HOST_UNREACHABLE: 387 pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))? 388 "FA denial: HA host unreachable": 389 "FA denial: code 81"; 390 break; 391 case REPLY_CODE_FA_NACK_ICMP_HA_PORT_UNREACHABLE: 392 pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))? 393 "FA denial: HA port unreachable": 394 "FA denial: code 82"; 395 break; 396 case REPLY_CODE_FA_NACK_ICMP_HA_UNREACHABLE: 397 pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))? 398 "FA denial: HA unreachable":"FA denial: code 88"; 399 break; 400 case REPLY_CODE_FA_NACK_UNIQUE_HOMEADDR_REQD: 401 pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))? 402 "FA denial: Unique Home Addr Required": 403 "FA denial: code 96"; 404 break; 405 case REPLY_CODE_FA_NACK_MISSING_NAI: 406 pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))? 407 "FA denial: Missing NAI": 408 "FA denial: code 97"; 409 break; 410 case REPLY_CODE_FA_NACK_MISSING_HOME_AGENT: 411 pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))? 412 "FA denial: Missing Home Agent": 413 "FA denial: code 98"; 414 break; 415 case REPLY_CODE_FA_NACK_UNKNOWN_CHALLENGE: 416 pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))? 417 "FA denial: Unknown Challenge": 418 "FA denial: code 104"; 419 break; 420 case REPLY_CODE_FA_NACK_MISSING_CHALLENGE: 421 pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))? 422 "FA denial: Missing Challenge": 423 "FA denial: code 105"; 424 break; 425 case REPLY_CODE_FA_NACK_MISSING_MN_FA: 426 pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))? 427 "FA denial: Missing Mobile-Foreign Key Extension": 428 "FA denial: code 106"; 429 break; 430 case REPLY_CODE_HA_NACK_UNSPECIFIED: 431 pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))? 432 "HA denial: unspecified":"HA denial: code 128"; 433 break; 434 case REPLY_CODE_HA_NACK_PROHIBITED: 435 pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))? 436 "HA denial: prohibited":"HA denial: code 129"; 437 break; 438 case REPLY_CODE_HA_NACK_RESOURCES: 439 pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))? 440 "HA denial: no resources":"HA denial: code 130"; 441 break; 442 case REPLY_CODE_HA_NACK_MN_AUTH: 443 pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))? 444 "HA denial: MN auth failed":"HA denial: code 131"; 445 break; 446 case REPLY_CODE_HA_NACK_FA_AUTH: 447 pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))? 448 "HA denial: FA auth failed":"HA denial: code 132"; 449 break; 450 case REPLY_CODE_HA_NACK_ID_MISMATCH: 451 pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))? 452 "HA denial: ID mismatch":"HA denial: code 133"; 453 break; 454 case REPLY_CODE_HA_NACK_BAD_REQUEST: 455 pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))? 456 "HA denial: bad request":"HA denial: code 134"; 457 break; 458 case REPLY_CODE_HA_NACK_TOO_MANY_BINDINGS: 459 pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))? 460 "HA denial: too many bindings": 461 "HA denial: code 135"; 462 break; 463 case REPLY_CODE_HA_NACK_BAD_HA_ADDRESS: 464 pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))? 465 "HA denial: bad HA address":"HA denial: code 136"; 466 break; 467 case REPLY_CODE_HA_NACK_BIDIR_TUNNEL_UNAVAILABLE: 468 pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))? 469 "HA denial: no reverse tunnel": 470 "HA denial: code 137"; 471 break; 472 case REPLY_CODE_HA_NACK_BIDIR_TUNNEL_NO_TBIT: 473 pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))? 474 "HA denial: reverse tunnel: no T-bit": 475 "HA denial: code 138"; 476 break; 477 case REPLY_CODE_HA_NACK_BIDIR_ENCAP_UNAVAILABLE: 478 pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))? 479 "HA denial: encapsulation unavailable": 480 "HA denial: code 139"; 481 break; 482 default: 483 pc = "?"; 484 break; 485 } 486 break; 487 488 default : 489 break; 490 } 491 if (flags & F_SUM) { 492 line = get_sum_line(); 493 494 if (pc != NULL) 495 (void) sprintf(line, "Mobile IP %s(%s)", pt, pc); 496 else 497 (void) sprintf(line, "Mobile IP %s", pt); 498 } 499 500 if (flags & F_DTAIL) { 501 show_header("MIP: ", "Mobile IP Header", fraglen); 502 show_space(); 503 504 if (*msg == REG_TYPE_REQ) { 505 (void) sprintf(get_line((char *)&rreq - 506 dlc_header, 1), "Registration header type = %s", 507 pt); 508 (void) sprintf(get_line( 509 (char *)(((uchar_t *)&rreq) + 1) - dlc_header, 1), 510 "%d... .... = %s simultaneous bindings ", 511 (rreq->Simultaneous_registration == 1)? 1 : 0, 512 (rreq->Simultaneous_registration == 1)? "":"no"); 513 (void) sprintf(get_line( 514 (char *)(((uchar_t *)&rreq) + 1) - dlc_header, 1), 515 ".%d.. .... = %s broadcast datagrams ", 516 (rreq->Broadcasts_desired == 1) ? 1 : 0, 517 (rreq->Broadcasts_desired == 1) ? "":"no"); 518 (void) sprintf(get_line( 519 (char *)(((uchar_t *)&rreq) + 1) - dlc_header, 1), 520 "..%d. .... = %s decapsulation by MN", 521 (rreq->Decapsulation_done_locally == 1) ? 1 : 0, 522 (rreq->Decapsulation_done_locally == 1) ? 523 "" : "no"); 524 (void) sprintf(get_line( 525 (char *)(((uchar_t *)&rreq) + 1) - dlc_header, 1), 526 "...%d .... = %s minimum encapsulation ", 527 (rreq->Minimal_encap_desired == 1) ? 1 : 0, 528 (rreq->Minimal_encap_desired == 1) ? "" : "no"); 529 (void) sprintf(get_line( 530 (char *)(((uchar_t *)&rreq) + 1) - dlc_header, 1), 531 ".... %d... = %s GRE encapsulation ", 532 (rreq->GRE_encap_desired == 1) ? 1 : 0, 533 (rreq->GRE_encap_desired == 1) ? "" : "no"); 534 (void) sprintf(get_line( 535 (char *)(((uchar_t *)&rreq) + 1) - dlc_header, 1), 536 ".... .%d.. = %s VJ hdr Compression ", 537 (rreq->VJ_compression_desired == 1) ? 1 : 0, 538 (rreq->VJ_compression_desired == 1) ? "" : "no"); 539 (void) sprintf(get_line( 540 (char *)(((uchar_t *)&rreq) + 1) - dlc_header, 1), 541 ".... ..%d. = %s reverse tunnel", 542 (rreq->BiDirectional_Tunnel_desired == 1) ? 1 : 0, 543 (rreq->BiDirectional_Tunnel_desired == 1) ? 544 "" : "no"); 545 if (ntohs(rreq->lifetime) == 0xffff) { 546 (void) sprintf(get_line( 547 (char *)&rreq->lifetime - dlc_header, 1), 548 "Life Time = 0xFFFF (infinity)"); 549 } else if (ntohs(rreq->lifetime) == 0) { 550 (void) sprintf(get_line( 551 (char *)&rreq->lifetime - dlc_header, 1), 552 "Life Time = 0 " 553 "(request for de-registration)"); 554 } else { 555 (void) sprintf(get_line( 556 (char *)&rreq->lifetime - dlc_header, 1), 557 "Life time = %d seconds", 558 ntohs(rreq->lifetime)); 559 } 560 addr_temp.s_addr = rreq->home_addr; 561 (void) sprintf(get_line( 562 (char *)&rreq->home_addr - dlc_header, 1), 563 "Home address = %s, %s", 564 inet_ntoa(addr_temp), 565 addrtoname(AF_INET, &addr_temp)); 566 addr_temp.s_addr = rreq->home_agent_addr; 567 (void) sprintf(get_line( 568 (char *)&rreq->home_agent_addr - dlc_header, 1), 569 "Home Agent address = %s, %s", 570 inet_ntoa(addr_temp), 571 addrtoname(AF_INET, &addr_temp)); 572 addr_temp.s_addr = rreq->care_of_addr; 573 (void) sprintf(get_line( 574 (char *)&rreq->care_of_addr - dlc_header, 1), 575 "Care of address = %s, %s", 576 inet_ntoa(addr_temp), 577 addrtoname(AF_INET, &addr_temp)); 578 (void) sprintf(get_line( 579 (char *)&rreq->identification - dlc_header, 1), 580 "Identification = 0x%x-%x", 581 ntohl(rreq->identification.high_bits), 582 ntohl(rreq->identification.low_bits)); 583 } else if (*msg == REG_TYPE_REP) { 584 (void) sprintf( 585 get_line((char *)&rrep->type - dlc_header, 1), 586 "Registration header type = %d (%s)", 587 (int)rrep->type, pt); 588 (void) sprintf(get_line((char *)&rrep - dlc_header, 1), 589 "Code = %d %s", (int)rrep->code, pc); 590 if (ntohs(rrep->lifetime) == 0xffff) { 591 (void) sprintf(get_line( 592 (char *)&rrep->lifetime - dlc_header, 1), 593 "Life time = 0xFFFF (infinity)"); 594 } else if (ntohs(rrep->lifetime) == 0) { 595 (void) sprintf(get_line( 596 (char *)&rrep->lifetime - dlc_header, 1), 597 ((rrep->code == REPLY_CODE_ACK) || 598 (rrep->code == 599 REPLY_CODE_ACK_NO_SIMULTANEOUS))? 600 "Life time = 0 (de-registeration success)" : 601 "Life time = 0 (de-registration failed)"); 602 } else { 603 (void) sprintf(get_line( 604 (char *)&rrep->lifetime - dlc_header, 1), 605 "Life time = %d seconds", 606 ntohs(rrep->lifetime)); 607 } 608 addr_temp.s_addr = rrep->home_addr; 609 (void) sprintf( 610 get_line((char *)&rrep->home_addr - dlc_header, 1), 611 "Home address = %s, %s", 612 inet_ntoa(addr_temp), 613 addrtoname(AF_INET, &addr_temp)); 614 addr_temp.s_addr = rrep->home_agent_addr; 615 (void) sprintf(get_line( 616 (char *)&rrep->home_agent_addr - dlc_header, 1), 617 "Home Agent address = %s, %s", 618 inet_ntoa(addr_temp), 619 addrtoname(AF_INET, &addr_temp)); 620 (void) sprintf(get_line( 621 (char *)&rrep->identification - dlc_header, 1), 622 "Identification = 0x%x-%x", 623 ntohl(rrep->identification.high_bits), 624 ntohl(rrep->identification.low_bits)); 625 } 626 fraglen = interpret_extensions(regext_data, regext_size, REG); 627 } 628 } 629 630 /*ARGSUSED*/ 631 static void spi_ext(uint8_t type, uint8_t this_ext_len, uchar_t *p) { 632 uint16_t spi_hi, spi_low; 633 char auth_prn_str[BUFLEN]; 634 635 /* SPI */ 636 GETSPI(p, spi_hi, spi_low); 637 (void) sprintf(get_line((char *)p - dlc_header, 1), 638 "Security Parameter Index = 0x%x%x", 639 ntohs(spi_hi), ntohs(spi_low)); 640 p += sizeof (spi_hi) + sizeof (spi_low); 641 this_ext_len -= sizeof (spi_hi) + sizeof (spi_low); 642 643 /* The rest is the authenticator; dump it in hex */ 644 dumphex(p, 645 /* don't write past our string buffer ... */ 646 (this_ext_len*3 > BUFLEN ? BUFLEN : this_ext_len), 647 auth_prn_str, 648 "Authenticator = %s"); 649 } 650 651 static void key_ext(uint8_t type, uint8_t this_ext_len, uchar_t *p) { 652 uint16_t alg, spi_hi, spi_low; 653 char *alg_string; 654 char *hafa = (type == MN_HA_KEY ? "HA" : "FA"); 655 char sec_msg[32]; 656 char auth_prn_str[BUFLEN]; 657 658 /* Algorithm Type */ 659 (void) memcpy(&alg, p, sizeof (alg)); 660 alg = ntohs(alg); 661 switch (alg) { 662 case KEY_ALG_NONE: 663 alg_string = "None"; 664 break; 665 case SA_MD5_MODE_PREF_SUF: 666 alg_string = "MD5/prefix+suffix"; 667 break; 668 case SA_HMAC_MD5: 669 alg_string = "HMAC MD5"; 670 break; 671 default: 672 alg_string = "Unknown"; 673 break; 674 } 675 (void) sprintf(get_line((char *)p-dlc_header, 1), 676 "Algorithm = 0x%x: %s", alg, alg_string); 677 p += sizeof (alg); 678 this_ext_len -= sizeof (alg); 679 680 /* AAA SPI */ 681 GETSPI(p, spi_hi, spi_low); 682 (void) sprintf(get_line((char *)p - dlc_header, 1), 683 "AAA Security Parameter Index = 0x%x%x", 684 ntohs(spi_hi), ntohs(spi_low)); 685 p += sizeof (spi_hi) + sizeof (spi_low); 686 this_ext_len -= sizeof (spi_hi) + sizeof (spi_low); 687 688 /* HA / FA SPI */ 689 GETSPI(p, spi_hi, spi_low); 690 (void) sprintf(get_line((char *)p - dlc_header, 1), 691 "%s Security Parameter Index = 0x%x%x", 692 hafa, ntohs(spi_hi), ntohs(spi_low)); 693 p += sizeof (spi_hi) + sizeof (spi_low); 694 this_ext_len -= sizeof (spi_hi) + sizeof (spi_low); 695 696 /* The rest is the security info; dump it in hex */ 697 sprintf(sec_msg, "%s Security Info = %%s", hafa); 698 dumphex(p, 699 /* don't write past our string buffer ... */ 700 (this_ext_len*3 > BUFLEN ? BUFLEN : this_ext_len), 701 auth_prn_str, 702 sec_msg); 703 } 704 705 /*ARGSUSED*/ 706 static void trav_ext(uint8_t type, uint8_t this_ext_len, uchar_t *p) { 707 struct in_addr addr_temp; 708 709 /* skip reserved */ 710 p += 2; 711 this_ext_len -= 2; 712 713 /* Mobile-Home Traversal Address */ 714 (void) memcpy(&(addr_temp.s_addr), p, sizeof (addr_temp.s_addr)); 715 (void) sprintf(get_line((char *)p-dlc_header, 1), 716 "Mobile-Home Traversal Address= %s, %s", 717 inet_ntoa(addr_temp), 718 addrtoname(AF_INET, &addr_temp)); 719 p += sizeof (addr_temp.s_addr); 720 this_ext_len -= sizeof (addr_temp.s_addr); 721 722 /* Home-Mobile Traversal Address */ 723 (void) memcpy(&(addr_temp.s_addr), p, sizeof (addr_temp.s_addr)); 724 (void) sprintf(get_line((char *)p-dlc_header, 1), 725 "Home-Mobile Traversal Address= %s, %s", 726 inet_ntoa(addr_temp), 727 addrtoname(AF_INET, &addr_temp)); 728 } 729 730 /*ARGSUSED*/ 731 static void empty_ext(uint8_t type, uint8_t this_ext_len, uchar_t *p) { 732 /* no payload */ 733 } 734 735 /*ARGSUSED*/ 736 static void nai_ext(uint8_t type, uint8_t this_ext_len, uchar_t *p) { 737 /* payload points to the NAI */ 738 char *desc = "Network Access Identifier = "; 739 size_t desclen = strlen(desc) + 1 + this_ext_len; 740 741 (void) snprintf(get_line((char *)p-dlc_header, 1), 742 desclen > MAXLINE ? MAXLINE : desclen, 743 "%s%s", desc, p); 744 } 745 746 /*ARGSUSED*/ 747 static void chall_ext(uint8_t type, uint8_t this_ext_len, uchar_t *p) { 748 char auth_prn_str[BUFLEN]; 749 750 /* payload points to the challenge */ 751 dumphex(p, 752 /* don't write past our string buffer ... */ 753 (this_ext_len*3 > BUFLEN ? BUFLEN / 3 : this_ext_len), 754 auth_prn_str, 755 "Challenge = %s"); 756 } 757 758 /*ARGSUSED*/ 759 static void ma_ext(uint8_t type, uint8_t this_ext_len, uchar_t *p) { 760 mobagtadvext_t adv_ext[1]; 761 int i, len; 762 struct in_addr temp_addr; 763 764 (void) memcpy(adv_ext, p - sizeof (exthdr_t), sizeof (*adv_ext)); 765 (void) sprintf(get_line(0, 0), "Sequence number = %d", 766 ntohs(adv_ext->sequence_num)); 767 (void) sprintf(get_line(0, 0), 768 "Registration lifetime = %d seconds", 769 ntohs(adv_ext->reg_lifetime)); 770 if (adv_ext->reg_bit) { 771 (void) sprintf(get_line(0, 0), 772 "1... .... = registration required " 773 "through FA"); 774 } else { 775 (void) sprintf(get_line(0, 0), 776 "0... .... = registration not required " 777 "through FA"); 778 } 779 if (adv_ext->busy_bit) { 780 (void) sprintf(get_line(0, 0), ".1.. .... = FA busy"); 781 } else { 782 (void) sprintf(get_line(0, 0), ".0.. .... = FA not busy"); 783 } 784 if (adv_ext->ha_bit) { 785 (void) sprintf(get_line(0, 0), "..1. .... = node is HA"); 786 } else { 787 (void) sprintf(get_line(0, 0), "..0. .... = node not HA"); 788 } 789 if (adv_ext->fa_bit) { 790 (void) sprintf(get_line(0, 0), "...1 .... = node is FA "); 791 } else { 792 (void) sprintf(get_line(0, 0), "...0 .... = node not FA "); 793 } 794 if (adv_ext->minencap_bit) { 795 (void) sprintf(get_line(0, 0), ".... 1... = minimal encapsulation " 796 "supported"); 797 } else { 798 (void) sprintf(get_line(0, 0), 799 ".... 0... = no minimal encapsulation"); 800 } 801 if (adv_ext->greencap_bit) { 802 (void) sprintf(get_line(0, 0), 803 ".... .1.. = GRE encapsulation supported"); 804 } else { 805 (void) sprintf(get_line(0, 0), 806 ".... .0.. = no GRE encapsulation"); 807 } 808 if (adv_ext->vanjacob_hdr_comp_bit) { 809 (void) sprintf(get_line(0, 0), 810 ".... ..1. = VJ header compression"); 811 } else { 812 (void) sprintf(get_line(0, 0), 813 ".... ..0. = no VJ header compression"); 814 } 815 if (adv_ext->reverse_tunnel_bit) { 816 (void) sprintf(get_line(0, 0), 817 ".... ...1 = reverse tunneling supported"); 818 } else { 819 (void) sprintf(get_line(0, 0), 820 ".... ...0 = no reverse tunneling"); 821 } 822 (void) sprintf(get_line(0, 0), 823 "Reserved Byte = 0x%x", adv_ext->reserved); 824 825 /* Parse out COA's */ 826 p += sizeof (*adv_ext); 827 len = this_ext_len + sizeof (exthdr_t); 828 /* this_ext_len is unsigned, and here we need a signed number */ 829 len -= sizeof (*adv_ext); 830 831 for (i = 0; len >= sizeof (temp_addr.s_addr); i++) { 832 memcpy(&(temp_addr.s_addr), p - sizeof (exthdr_t), 833 sizeof (temp_addr.s_addr)); 834 835 (void) sprintf(get_line(0, 0), 836 "Care of address-%d = %s, %s", i, 837 inet_ntoa(temp_addr), 838 addrtoname(AF_INET, &temp_addr)); 839 840 p += sizeof (temp_addr); 841 len -= sizeof (temp_addr); 842 } 843 } 844 845 /*ARGSUSED*/ 846 static void prefix_ext(uint8_t type, uint8_t this_ext_len, uchar_t *p) { 847 int i; 848 849 for (i = 0; i < this_ext_len; i++) { 850 (void) sprintf(get_line(0, 0), 851 "Prefix length of router address[%d] " 852 "= %d bits", 853 i, p[i]); 854 } 855 } 856 857 /*ARGSUSED*/ 858 static void unk_ext(uint8_t type, uint8_t this_ext_len, uchar_t *p) { 859 char auth_prn_str[BUFLEN]; 860 861 /* Unknown extension; just dump the rest of the payload */ 862 dumphex(p, 863 /* don't write past our string buffer ... */ 864 (this_ext_len*3 > BUFLEN ? BUFLEN : this_ext_len), 865 auth_prn_str, 866 "Payload = %s"); 867 } 868