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