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