1 /* 2 * Copyright (C) 2000 Alfredo Andres Omella. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in 12 * the documentation and/or other materials provided with the 13 * distribution. 14 * 3. The names of the authors may not be used to endorse or promote 15 * products derived from this software without specific prior 16 * written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 21 */ 22 23 /* \summary: Radius protocol printer */ 24 25 /* 26 * Radius printer routines as specified on: 27 * 28 * RFC 2865: 29 * "Remote Authentication Dial In User Service (RADIUS)" 30 * 31 * RFC 2866: 32 * "RADIUS Accounting" 33 * 34 * RFC 2867: 35 * "RADIUS Accounting Modifications for Tunnel Protocol Support" 36 * 37 * RFC 2868: 38 * "RADIUS Attributes for Tunnel Protocol Support" 39 * 40 * RFC 2869: 41 * "RADIUS Extensions" 42 * 43 * RFC 3162: 44 * "RADIUS and IPv6" 45 * 46 * RFC 3580: 47 * "IEEE 802.1X Remote Authentication Dial In User Service (RADIUS)" 48 * "Usage Guidelines" 49 * 50 * RFC 4072: 51 * "Diameter Extensible Authentication Protocol (EAP) Application" 52 * 53 * RFC 4675: 54 * "RADIUS Attributes for Virtual LAN and Priority Support" 55 * 56 * RFC 4818: 57 * "RADIUS Delegated-IPv6-Prefix Attribute" 58 * 59 * RFC 4849: 60 * "RADIUS Filter Rule Attribute" 61 * 62 * RFC 5090: 63 * "RADIUS Extension for Digest Authentication" 64 * 65 * RFC 5176: 66 * "Dynamic Authorization Extensions to RADIUS" 67 * 68 * RFC 5447: 69 * "Diameter Mobile IPv6" 70 * 71 * RFC 5580: 72 * "Carrying Location Objects in RADIUS and Diameter" 73 * 74 * RFC 6572: 75 * "RADIUS Support for Proxy Mobile IPv6" 76 * 77 * RFC 7155: 78 * "Diameter Network Access Server Application" 79 * 80 * Alfredo Andres Omella (aandres@s21sec.com) v0.1 2000/09/15 81 * 82 * TODO: Among other things to print ok MacIntosh and Vendor values 83 */ 84 85 #include <sys/cdefs.h> 86 #ifndef lint 87 __RCSID("$NetBSD: print-radius.c,v 1.11 2024/09/02 16:15:32 christos Exp $"); 88 #endif 89 90 #include <config.h> 91 92 #include "netdissect-stdinc.h" 93 94 #include <string.h> 95 96 #include "netdissect-ctype.h" 97 98 #include "netdissect.h" 99 #include "addrtoname.h" 100 #include "extract.h" 101 #include "oui.h" 102 #include "ntp.h" 103 104 105 #define TAM_SIZE(x) (sizeof(x)/sizeof(x[0]) ) 106 107 #define PRINT_HEX(bytes_len, ptr_data) \ 108 while(bytes_len) \ 109 { \ 110 ND_PRINT("%02X", GET_U_1(ptr_data)); \ 111 ptr_data++; \ 112 bytes_len--; \ 113 } 114 115 116 /* Radius packet codes */ 117 /* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-27 */ 118 #define RADCMD_ACCESS_REQ 1 /* Access-Request */ 119 #define RADCMD_ACCESS_ACC 2 /* Access-Accept */ 120 #define RADCMD_ACCESS_REJ 3 /* Access-Reject */ 121 #define RADCMD_ACCOUNT_REQ 4 /* Accounting-Request */ 122 #define RADCMD_ACCOUNT_RES 5 /* Accounting-Response */ 123 #define RADCMD_ACCESS_CHA 11 /* Access-Challenge */ 124 #define RADCMD_STATUS_SER 12 /* Status-Server */ 125 #define RADCMD_STATUS_CLI 13 /* Status-Client */ 126 #define RADCMD_DISCON_REQ 40 /* Disconnect-Request */ 127 #define RADCMD_DISCON_ACK 41 /* Disconnect-ACK */ 128 #define RADCMD_DISCON_NAK 42 /* Disconnect-NAK */ 129 #define RADCMD_COA_REQ 43 /* CoA-Request */ 130 #define RADCMD_COA_ACK 44 /* CoA-ACK */ 131 #define RADCMD_COA_NAK 45 /* CoA-NAK */ 132 #define RADCMD_RESERVED 255 /* Reserved */ 133 134 static const struct tok radius_command_values[] = { 135 { RADCMD_ACCESS_REQ, "Access-Request" }, 136 { RADCMD_ACCESS_ACC, "Access-Accept" }, 137 { RADCMD_ACCESS_REJ, "Access-Reject" }, 138 { RADCMD_ACCOUNT_REQ, "Accounting-Request" }, 139 { RADCMD_ACCOUNT_RES, "Accounting-Response" }, 140 { RADCMD_ACCESS_CHA, "Access-Challenge" }, 141 { RADCMD_STATUS_SER, "Status-Server" }, 142 { RADCMD_STATUS_CLI, "Status-Client" }, 143 { RADCMD_DISCON_REQ, "Disconnect-Request" }, 144 { RADCMD_DISCON_ACK, "Disconnect-ACK" }, 145 { RADCMD_DISCON_NAK, "Disconnect-NAK" }, 146 { RADCMD_COA_REQ, "CoA-Request" }, 147 { RADCMD_COA_ACK, "CoA-ACK" }, 148 { RADCMD_COA_NAK, "CoA-NAK" }, 149 { RADCMD_RESERVED, "Reserved" }, 150 { 0, NULL} 151 }; 152 153 /********************************/ 154 /* Begin Radius Attribute types */ 155 /********************************/ 156 #define SERV_TYPE 6 157 #define FRM_IPADDR 8 158 #define LOG_IPHOST 14 159 #define LOG_SERVICE 15 160 #define FRM_IPX 23 161 #define SESSION_TIMEOUT 27 162 #define IDLE_TIMEOUT 28 163 #define FRM_ATALK_LINK 37 164 #define FRM_ATALK_NETWORK 38 165 166 #define ACCT_DELAY 41 167 #define ACCT_SESSION_TIME 46 168 169 #define EGRESS_VLAN_ID 56 170 #define EGRESS_VLAN_NAME 58 171 172 #define TUNNEL_TYPE 64 173 #define TUNNEL_MEDIUM 65 174 #define TUNNEL_CLIENT_END 66 175 #define TUNNEL_SERVER_END 67 176 #define TUNNEL_PASS 69 177 178 #define ARAP_PASS 70 179 #define ARAP_FEATURES 71 180 181 #define EAP_MESSAGE 79 182 183 #define TUNNEL_PRIV_GROUP 81 184 #define TUNNEL_ASSIGN_ID 82 185 #define TUNNEL_PREFERENCE 83 186 187 #define ARAP_CHALLENGE_RESP 84 188 #define ACCT_INT_INTERVAL 85 189 190 #define TUNNEL_CLIENT_AUTH 90 191 #define TUNNEL_SERVER_AUTH 91 192 193 #define ERROR_CAUSE 101 194 /********************************/ 195 /* End Radius Attribute types */ 196 /********************************/ 197 198 #define RFC4675_TAGGED 0x31 199 #define RFC4675_UNTAGGED 0x32 200 201 static const struct tok rfc4675_tagged[] = { 202 { RFC4675_TAGGED, "Tagged" }, 203 { RFC4675_UNTAGGED, "Untagged" }, 204 { 0, NULL} 205 }; 206 207 208 static void print_attr_string(netdissect_options *, const u_char *, u_int, u_short ); 209 static void print_attr_num(netdissect_options *, const u_char *, u_int, u_short ); 210 static void print_vendor_attr(netdissect_options *, const u_char *, u_int, u_short ); 211 static void print_attr_address(netdissect_options *, const u_char *, u_int, u_short); 212 static void print_attr_address6(netdissect_options *, const u_char *, u_int, u_short); 213 static void print_attr_netmask6(netdissect_options *, const u_char *, u_int, u_short); 214 static void print_attr_mip6_home_link_prefix(netdissect_options *, const u_char *, u_int, u_short); 215 static void print_attr_operator_name(netdissect_options *, const u_char *, u_int, u_short); 216 static void print_attr_location_information(netdissect_options *, const u_char *, u_int, u_short); 217 static void print_attr_location_data(netdissect_options *, const u_char *, u_int, u_short); 218 static void print_basic_location_policy_rules(netdissect_options *, const u_char *, u_int, u_short); 219 static void print_attr_time(netdissect_options *, const u_char *, u_int, u_short); 220 static void print_attr_vector64(netdissect_options *, const u_char *, u_int, u_short); 221 static void print_attr_strange(netdissect_options *, const u_char *, u_int, u_short); 222 223 224 struct radius_hdr { nd_uint8_t code; /* Radius packet code */ 225 nd_uint8_t id; /* Radius packet id */ 226 nd_uint16_t len; /* Radius total length */ 227 nd_byte auth[16]; /* Authenticator */ 228 }; 229 230 #define MIN_RADIUS_LEN 20 231 232 struct radius_attr { nd_uint8_t type; /* Attribute type */ 233 nd_uint8_t len; /* Attribute length */ 234 }; 235 236 237 /* Service-Type Attribute standard values */ 238 /* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-4 */ 239 static const char *serv_type[]={ NULL, 240 "Login", 241 "Framed", 242 "Callback Login", 243 "Callback Framed", 244 "Outbound", 245 "Administrative", 246 "NAS Prompt", 247 "Authenticate Only", 248 "Callback NAS Prompt", 249 /* ^ [0, 9] ^ */ 250 "Call Check", 251 "Callback Administrative", 252 "Voice", 253 "Fax", 254 "Modem Relay", 255 "IAPP-Register", 256 "IAPP-AP-Check", 257 "Authorize Only", 258 "Framed-Management", 259 "Additional-Authorization", 260 /* ^ [10, 19] ^ */ 261 }; 262 263 /* Framed-Protocol Attribute standard values */ 264 /* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-5 */ 265 static const char *frm_proto[]={ NULL, 266 "PPP", 267 "SLIP", 268 "ARAP", 269 "Gandalf proprietary", 270 "Xylogics IPX/SLIP", 271 "X.75 Synchronous", 272 "GPRS PDP Context", 273 }; 274 275 /* Framed-Routing Attribute standard values */ 276 /* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-6 */ 277 static const char *frm_routing[]={ "None", 278 "Send", 279 "Listen", 280 "Send&Listen", 281 }; 282 283 /* Framed-Compression Attribute standard values */ 284 /* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-7 */ 285 static const char *frm_comp[]={ "None", 286 "VJ TCP/IP", 287 "IPX", 288 "Stac-LZS", 289 }; 290 291 /* Login-Service Attribute standard values */ 292 /* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-8 */ 293 static const char *login_serv[]={ "Telnet", 294 "Rlogin", 295 "TCP Clear", 296 "PortMaster(proprietary)", 297 "LAT", 298 "X.25-PAD", 299 "X.25-T3POS", 300 "Unassigned", 301 "TCP Clear Quiet", 302 }; 303 304 305 /* Termination-Action Attribute standard values */ 306 /* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-9 */ 307 static const char *term_action[]={ "Default", 308 "RADIUS-Request", 309 }; 310 311 /* Ingress-Filters Attribute standard values */ 312 static const char *ingress_filters[]={ NULL, 313 "Enabled", 314 "Disabled", 315 }; 316 317 /* NAS-Port-Type Attribute standard values */ 318 /* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-13 */ 319 static const char *nas_port_type[]={ "Async", 320 "Sync", 321 "ISDN Sync", 322 "ISDN Async V.120", 323 "ISDN Async V.110", 324 "Virtual", 325 "PIAFS", 326 "HDLC Clear Channel", 327 "X.25", 328 "X.75", 329 /* ^ [0, 9] ^ */ 330 "G.3 Fax", 331 "SDSL", 332 "ADSL-CAP", 333 "ADSL-DMT", 334 "ISDN-DSL", 335 "Ethernet", 336 "xDSL", 337 "Cable", 338 "Wireless - Other", 339 "Wireless - IEEE 802.11", 340 /* ^ [10, 19] ^ */ 341 "Token-Ring", 342 "FDDI", 343 "Wireless - CDMA200", 344 "Wireless - UMTS", 345 "Wireless - 1X-EV", 346 "IAPP", 347 "FTTP", 348 "Wireless - IEEE 802.16", 349 "Wireless - IEEE 802.20", 350 "Wireless - IEEE 802.22", 351 /* ^ [20, 29] ^ */ 352 "PPPoA", 353 "PPPoEoA", 354 "PPPoEoE", 355 "PPPoEoVLAN", 356 "PPPoEoQinQ", 357 "xPON", 358 "Wireless - XGP", 359 "WiMAX Pre-Release 8 IWK Function", 360 "WIMAX-WIFI-IWK", 361 "WIMAX-SFF", 362 /* ^ [30, 39] ^ */ 363 "WIMAX-HA-LMA", 364 "WIMAX-DHCP", 365 "WIMAX-LBS", 366 "WIMAX-WVS", 367 }; 368 369 /* Acct-Status-Type Accounting Attribute standard values */ 370 /* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-10 */ 371 static const char *acct_status[]={ NULL, 372 "Start", 373 "Stop", 374 "Interim-Update", 375 "Unassigned", 376 "Unassigned", 377 "Unassigned", 378 "Accounting-On", 379 "Accounting-Off", 380 "Tunnel-Start", 381 /* ^ [0, 9] ^ */ 382 "Tunnel-Stop", 383 "Tunnel-Reject", 384 "Tunnel-Link-Start", 385 "Tunnel-Link-Stop", 386 "Tunnel-Link-Reject", 387 "Failed", 388 }; 389 390 /* Acct-Authentic Accounting Attribute standard values */ 391 /* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-11 */ 392 static const char *acct_auth[]={ NULL, 393 "RADIUS", 394 "Local", 395 "Remote", 396 "Diameter", 397 }; 398 399 /* Acct-Terminate-Cause Accounting Attribute standard values */ 400 /* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-12 */ 401 static const char *acct_term[]={ NULL, 402 "User Request", 403 "Lost Carrier", 404 "Lost Service", 405 "Idle Timeout", 406 "Session Timeout", 407 "Admin Reset", 408 "Admin Reboot", 409 "Port Error", 410 "NAS Error", 411 /* ^ [0, 9] ^ */ 412 "NAS Request", 413 "NAS Reboot", 414 "Port Unneeded", 415 "Port Preempted", 416 "Port Suspended", 417 "Service Unavailable", 418 "Callback", 419 "User Error", 420 "Host Request", 421 "Supplicant Restart", 422 /* ^ [10, 19] ^ */ 423 "Reauthentication Failure", 424 "Port Reinitialized", 425 "Port Administratively Disabled", 426 "Lost Power", 427 }; 428 429 /* Tunnel-Type Attribute standard values */ 430 /* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-14 */ 431 static const char *tunnel_type[]={ NULL, 432 "PPTP", 433 "L2F", 434 "L2TP", 435 "ATMP", 436 "VTP", 437 "AH", 438 "IP-IP", 439 "MIN-IP-IP", 440 "ESP", 441 /* ^ [0, 9] ^ */ 442 "GRE", 443 "DVS", 444 "IP-in-IP Tunneling", 445 "VLAN", 446 }; 447 448 /* Tunnel-Medium-Type Attribute standard values */ 449 /* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-15 */ 450 static const char *tunnel_medium[]={ NULL, 451 "IPv4", 452 "IPv6", 453 "NSAP", 454 "HDLC", 455 "BBN 1822", 456 "802", 457 "E.163", 458 "E.164", 459 "F.69", 460 /* ^ [0, 9] ^ */ 461 "X.121", 462 "IPX", 463 "Appletalk", 464 "Decnet IV", 465 "Banyan Vines", 466 "E.164 with NSAP subaddress", 467 }; 468 469 /* ARAP-Zone-Access Attribute standard values */ 470 /* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-16 */ 471 static const char *arap_zone[]={ NULL, 472 "Only access to dfl zone", 473 "Use zone filter inc.", 474 "Not used", 475 "Use zone filter exc.", 476 }; 477 478 /* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-17 */ 479 static const char *prompt[]={ "No Echo", 480 "Echo", 481 }; 482 483 /* Error-Cause standard values */ 484 /* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-18 */ 485 #define ERROR_CAUSE_RESIDUAL_CONTEXT_REMOVED 201 486 #define ERROR_CAUSE_INVALID_EAP_PACKET 202 487 #define ERROR_CAUSE_UNSUPPORTED_ATTRIBUTE 401 488 #define ERROR_CAUSE_MISSING_ATTRIBUTE 402 489 #define ERROR_CAUSE_NAS_IDENTIFICATION_MISMATCH 403 490 #define ERROR_CAUSE_INVALID_REQUEST 404 491 #define ERROR_CAUSE_UNSUPPORTED_SERVICE 405 492 #define ERROR_CAUSE_UNSUPPORTED_EXTENSION 406 493 #define ERROR_CAUSE_INVALID_ATTRIBUTE_VALUE 407 494 #define ERROR_CAUSE_ADMINISTRATIVELY_PROHIBITED 501 495 #define ERROR_CAUSE_PROXY_REQUEST_NOT_ROUTABLE 502 496 #define ERROR_CAUSE_SESSION_CONTEXT_NOT_FOUND 503 497 #define ERROR_CAUSE_SESSION_CONTEXT_NOT_REMOVABLE 504 498 #define ERROR_CAUSE_PROXY_PROCESSING_ERROR 505 499 #define ERROR_CAUSE_RESOURCES_UNAVAILABLE 506 500 #define ERROR_CAUSE_REQUEST_INITIATED 507 501 #define ERROR_CAUSE_MULTIPLE_SESSION_SELECTION_UNSUPPORTED 508 502 #define ERROR_CAUSE_LOCATION_INFO_REQUIRED 509 503 static const struct tok errorcausetype[] = { 504 { ERROR_CAUSE_RESIDUAL_CONTEXT_REMOVED, "Residual Session Context Removed" }, 505 { ERROR_CAUSE_INVALID_EAP_PACKET, "Invalid EAP Packet (Ignored)" }, 506 { ERROR_CAUSE_UNSUPPORTED_ATTRIBUTE, "Unsupported Attribute" }, 507 { ERROR_CAUSE_MISSING_ATTRIBUTE, "Missing Attribute" }, 508 { ERROR_CAUSE_NAS_IDENTIFICATION_MISMATCH, "NAS Identification Mismatch" }, 509 { ERROR_CAUSE_INVALID_REQUEST, "Invalid Request" }, 510 { ERROR_CAUSE_UNSUPPORTED_SERVICE, "Unsupported Service" }, 511 { ERROR_CAUSE_UNSUPPORTED_EXTENSION, "Unsupported Extension" }, 512 { ERROR_CAUSE_INVALID_ATTRIBUTE_VALUE, "Invalid Attribute Value" }, 513 { ERROR_CAUSE_ADMINISTRATIVELY_PROHIBITED, "Administratively Prohibited" }, 514 { ERROR_CAUSE_PROXY_REQUEST_NOT_ROUTABLE, "Request Not Routable (Proxy)" }, 515 { ERROR_CAUSE_SESSION_CONTEXT_NOT_FOUND, "Session Context Not Found" }, 516 { ERROR_CAUSE_SESSION_CONTEXT_NOT_REMOVABLE, "Session Context Not Removable" }, 517 { ERROR_CAUSE_PROXY_PROCESSING_ERROR, "Other Proxy Processing Error" }, 518 { ERROR_CAUSE_RESOURCES_UNAVAILABLE, "Resources Unavailable" }, 519 { ERROR_CAUSE_REQUEST_INITIATED, "Request Initiated" }, 520 { ERROR_CAUSE_MULTIPLE_SESSION_SELECTION_UNSUPPORTED, "Multiple Session Selection Unsupported" }, 521 { ERROR_CAUSE_LOCATION_INFO_REQUIRED, "Location Info Required" }, 522 { 0, NULL } 523 }; 524 525 /* MIP6-Feature-Vector standard values */ 526 /* https://www.iana.org/assignments/aaa-parameters/aaa-parameters.xhtml */ 527 #define MIP6_INTEGRATED 0x0000000000000001 528 #define LOCAL_HOME_AGENT_ASSIGNMENT 0x0000000000000002 529 #define PMIP6_SUPPORTED 0x0000010000000000 530 #define IP4_HOA_SUPPORTED 0x0000020000000000 531 #define LOCAL_MAG_ROUTING_SUPPORTED 0x0000040000000000 532 #define ASSIGN_LOCAL_IP 0x0000080000000000 533 #define MIP4_SUPPORTED 0x0000100000000000 534 #define OPTIMIZED_IDLE_MODE_MOBILITY 0x0000200000000000 535 #define GTPv2_SUPPORTED 0x0000400000000000 536 #define IP4_TRANSPORT_SUPPORTED 0x0000800000000000 537 #define IP4_HOA_ONLY_SUPPORTED 0x0001000000000000 538 #define INTER_MAG_ROUTING_SUPPORTED 0x0002000000000000 539 static const struct mip6_feature_vector { 540 uint64_t v; 541 const char *s; 542 } mip6_feature_vector[] = { 543 { MIP6_INTEGRATED, "MIP6_INTEGRATED" }, 544 { LOCAL_HOME_AGENT_ASSIGNMENT, "LOCAL_HOME_AGENT_ASSIGNMENT" }, 545 { PMIP6_SUPPORTED, "PMIP6_SUPPORTED" }, 546 { IP4_HOA_SUPPORTED, "IP4_HOA_SUPPORTED" }, 547 { LOCAL_MAG_ROUTING_SUPPORTED, "LOCAL_MAG_ROUTING_SUPPORTED" }, 548 { ASSIGN_LOCAL_IP, "ASSIGN_LOCAL_IP" }, 549 { MIP4_SUPPORTED, "MIP4_SUPPORTED" }, 550 { OPTIMIZED_IDLE_MODE_MOBILITY, "OPTIMIZED_IDLE_MODE_MOBILITY" }, 551 { GTPv2_SUPPORTED, "GTPv2_SUPPORTED" }, 552 { IP4_TRANSPORT_SUPPORTED, "IP4_TRANSPORT_SUPPORTED" }, 553 { IP4_HOA_ONLY_SUPPORTED, "IP4_HOA_ONLY_SUPPORTED" }, 554 { INTER_MAG_ROUTING_SUPPORTED, "INTER_MAG_ROUTING_SUPPORTED" }, 555 }; 556 557 /* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-19 */ 558 #define OPERATOR_NAME_TADIG 0x30 559 #define OPERATOR_NAME_REALM 0x31 560 #define OPERATOR_NAME_E212 0x32 561 #define OPERATOR_NAME_ICC 0x33 562 static const struct tok operator_name_vector[] = { 563 { OPERATOR_NAME_TADIG, "TADIG" }, 564 { OPERATOR_NAME_REALM, "REALM" }, 565 { OPERATOR_NAME_E212, "E212" }, 566 { OPERATOR_NAME_ICC, "ICC" }, 567 { 0, NULL } 568 }; 569 570 /* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-20 */ 571 #define LOCATION_INFORMATION_CODE_CIVIC 0 572 #define LOCATION_INFORMATION_CODE_GEOSPATIAL 1 573 static const struct tok location_information_code_vector[] = { 574 { LOCATION_INFORMATION_CODE_CIVIC , "Civic" }, 575 { LOCATION_INFORMATION_CODE_GEOSPATIAL, "Geospatial" }, 576 { 0, NULL } 577 }; 578 579 /* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-21 */ 580 #define LOCATION_INFORMATION_ENTITY_USER 0 581 #define LOCATION_INFORMATION_ENTITY_RADIUS 1 582 static const struct tok location_information_entity_vector[] = { 583 { LOCATION_INFORMATION_ENTITY_USER, "User" }, 584 { LOCATION_INFORMATION_ENTITY_RADIUS, "RADIUS" }, 585 { 0, NULL } 586 }; 587 588 /* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-22 */ 589 static const struct tok blpr_bm[] = { 590 { 0x0001, "MBZ-15" }, 591 { 0x0002, "MBZ-14" }, 592 { 0x0004, "MBZ-13" }, 593 { 0x0008, "MBZ-12" }, 594 { 0x0010, "MBZ-11" }, 595 { 0x0020, "MBZ-10" }, 596 { 0x0040, "MBZ-9" }, 597 { 0x0080, "MBZ-8" }, 598 { 0x0100, "MBZ-7" }, 599 { 0x0200, "MBZ-6" }, 600 { 0x0400, "MBZ-5" }, 601 { 0x0800, "MBZ-4" }, 602 { 0x1000, "MBZ-3" }, 603 { 0x2000, "MBZ-2" }, 604 { 0x4000, "MBZ-1" }, 605 { 0x8000, "Retransmission Allowed" }, 606 { 0, NULL } 607 }; 608 609 /* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-2 */ 610 static const struct attrtype { 611 const char *name; /* Attribute name */ 612 const char **subtypes; /* Standard Values (if any) */ 613 u_char siz_subtypes; /* Size of total standard values */ 614 u_char first_subtype; /* First standard value is 0 or 1 */ 615 void (*print_func)(netdissect_options *, const u_char *, u_int, u_short); 616 } attr_type[]= 617 { 618 { NULL, NULL, 0, 0, NULL }, 619 { "User-Name", NULL, 0, 0, print_attr_string }, 620 { "User-Password", NULL, 0, 0, NULL }, 621 { "CHAP-Password", NULL, 0, 0, NULL }, 622 { "NAS-IP-Address", NULL, 0, 0, print_attr_address }, 623 { "NAS-Port", NULL, 0, 0, print_attr_num }, 624 { "Service-Type", serv_type, TAM_SIZE(serv_type)-1, 1, print_attr_num }, 625 { "Framed-Protocol", frm_proto, TAM_SIZE(frm_proto)-1, 1, print_attr_num }, 626 { "Framed-IP-Address", NULL, 0, 0, print_attr_address }, 627 { "Framed-IP-Netmask", NULL, 0, 0, print_attr_address }, 628 /* ^ [0, 9] ^ */ 629 { "Framed-Routing", frm_routing, TAM_SIZE(frm_routing), 0, print_attr_num }, 630 { "Filter-Id", NULL, 0, 0, print_attr_string }, 631 { "Framed-MTU", NULL, 0, 0, print_attr_num }, 632 { "Framed-Compression", frm_comp, TAM_SIZE(frm_comp), 0, print_attr_num }, 633 { "Login-IP-Host", NULL, 0, 0, print_attr_address }, 634 { "Login-Service", login_serv, TAM_SIZE(login_serv), 0, print_attr_num }, 635 { "Login-TCP-Port", NULL, 0, 0, print_attr_num }, 636 { "Unassigned", NULL, 0, 0, NULL }, /*17*/ 637 { "Reply-Message", NULL, 0, 0, print_attr_string }, 638 { "Callback-Number", NULL, 0, 0, print_attr_string }, 639 /* ^ [10, 19] ^ */ 640 { "Callback-Id", NULL, 0, 0, print_attr_string }, 641 { "Unassigned", NULL, 0, 0, NULL }, /*21*/ 642 { "Framed-Route", NULL, 0, 0, print_attr_string }, 643 { "Framed-IPX-Network", NULL, 0, 0, print_attr_num }, 644 { "State", NULL, 0, 0, print_attr_string }, 645 { "Class", NULL, 0, 0, print_attr_string }, 646 { "Vendor-Specific", NULL, 0, 0, print_vendor_attr }, 647 { "Session-Timeout", NULL, 0, 0, print_attr_num }, 648 { "Idle-Timeout", NULL, 0, 0, print_attr_num }, 649 { "Termination-Action", term_action, TAM_SIZE(term_action), 0, print_attr_num }, 650 /* ^ [20, 29] ^ */ 651 { "Called-Station-Id", NULL, 0, 0, print_attr_string }, 652 { "Calling-Station-Id", NULL, 0, 0, print_attr_string }, 653 { "NAS-Identifier", NULL, 0, 0, print_attr_string }, 654 { "Proxy-State", NULL, 0, 0, print_attr_string }, 655 { "Login-LAT-Service", NULL, 0, 0, print_attr_string }, 656 { "Login-LAT-Node", NULL, 0, 0, print_attr_string }, 657 { "Login-LAT-Group", NULL, 0, 0, print_attr_string }, 658 { "Framed-AppleTalk-Link", NULL, 0, 0, print_attr_num }, 659 { "Framed-AppleTalk-Network", NULL, 0, 0, print_attr_num }, 660 { "Framed-AppleTalk-Zone", NULL, 0, 0, print_attr_string }, 661 /* ^ [30, 39] ^ */ 662 { "Acct-Status-Type", acct_status, TAM_SIZE(acct_status)-1, 1, print_attr_num }, 663 { "Acct-Delay-Time", NULL, 0, 0, print_attr_num }, 664 { "Acct-Input-Octets", NULL, 0, 0, print_attr_num }, 665 { "Acct-Output-Octets", NULL, 0, 0, print_attr_num }, 666 { "Acct-Session-Id", NULL, 0, 0, print_attr_string }, 667 { "Acct-Authentic", acct_auth, TAM_SIZE(acct_auth)-1, 1, print_attr_num }, 668 { "Acct-Session-Time", NULL, 0, 0, print_attr_num }, 669 { "Acct-Input-Packets", NULL, 0, 0, print_attr_num }, 670 { "Acct-Output-Packets", NULL, 0, 0, print_attr_num }, 671 { "Acct-Terminate-Cause", acct_term, TAM_SIZE(acct_term)-1, 1, print_attr_num }, 672 /* ^ [40, 49] ^ */ 673 { "Acct-Multi-Session-Id", NULL, 0, 0, print_attr_string }, 674 { "Acct-Link-Count", NULL, 0, 0, print_attr_num }, 675 { "Acct-Input-Gigawords", NULL, 0, 0, print_attr_num }, 676 { "Acct-Output-Gigawords", NULL, 0, 0, print_attr_num }, 677 { "Unassigned", NULL, 0, 0, NULL }, /*54*/ 678 { "Event-Timestamp", NULL, 0, 0, print_attr_time }, 679 { "Egress-VLANID", NULL, 0, 0, print_attr_num }, 680 { "Ingress-Filters", ingress_filters, TAM_SIZE(ingress_filters)-1, 1, print_attr_num }, 681 { "Egress-VLAN-Name", NULL, 0, 0, print_attr_string }, 682 { "User-Priority-Table", NULL, 0, 0, NULL }, 683 /* ^ [50, 59] ^ */ 684 { "CHAP-Challenge", NULL, 0, 0, print_attr_string }, 685 { "NAS-Port-Type", nas_port_type, TAM_SIZE(nas_port_type), 0, print_attr_num }, 686 { "Port-Limit", NULL, 0, 0, print_attr_num }, 687 { "Login-LAT-Port", NULL, 0, 0, print_attr_string }, /*63*/ 688 { "Tunnel-Type", tunnel_type, TAM_SIZE(tunnel_type)-1, 1, print_attr_num }, 689 { "Tunnel-Medium-Type", tunnel_medium, TAM_SIZE(tunnel_medium)-1, 1, print_attr_num }, 690 { "Tunnel-Client-Endpoint", NULL, 0, 0, print_attr_string }, 691 { "Tunnel-Server-Endpoint", NULL, 0, 0, print_attr_string }, 692 { "Acct-Tunnel-Connection", NULL, 0, 0, print_attr_string }, 693 { "Tunnel-Password", NULL, 0, 0, print_attr_string }, 694 /* ^ [60, 69] ^ */ 695 { "ARAP-Password", NULL, 0, 0, print_attr_strange }, 696 { "ARAP-Features", NULL, 0, 0, print_attr_strange }, 697 { "ARAP-Zone-Access", arap_zone, TAM_SIZE(arap_zone)-1, 1, print_attr_num }, /*72*/ 698 { "ARAP-Security", NULL, 0, 0, print_attr_string }, 699 { "ARAP-Security-Data", NULL, 0, 0, print_attr_string }, 700 { "Password-Retry", NULL, 0, 0, print_attr_num }, 701 { "Prompt", prompt, TAM_SIZE(prompt), 0, print_attr_num }, 702 { "Connect-Info", NULL, 0, 0, print_attr_string }, 703 { "Configuration-Token", NULL, 0, 0, print_attr_string }, 704 { "EAP-Message", NULL, 0, 0, print_attr_string }, 705 /* ^ [70, 79] ^ */ 706 { "Message-Authenticator", NULL, 0, 0, print_attr_string }, /*80*/ 707 { "Tunnel-Private-Group-ID", NULL, 0, 0, print_attr_string }, 708 { "Tunnel-Assignment-ID", NULL, 0, 0, print_attr_string }, 709 { "Tunnel-Preference", NULL, 0, 0, print_attr_num }, 710 { "ARAP-Challenge-Response", NULL, 0, 0, print_attr_strange }, 711 { "Acct-Interim-Interval", NULL, 0, 0, print_attr_num }, 712 { "Acct-Tunnel-Packets-Lost", NULL, 0, 0, print_attr_num }, /*86*/ 713 { "NAS-Port-Id", NULL, 0, 0, print_attr_string }, 714 { "Framed-Pool", NULL, 0, 0, print_attr_string }, 715 { "CUI", NULL, 0, 0, print_attr_string }, 716 /* ^ [80, 89] ^ */ 717 { "Tunnel-Client-Auth-ID", NULL, 0, 0, print_attr_string }, 718 { "Tunnel-Server-Auth-ID", NULL, 0, 0, print_attr_string }, 719 { "NAS-Filter-Rule", NULL, 0, 0, print_attr_string }, 720 { "Unassigned", NULL, 0, 0, NULL }, /*93*/ 721 { "Originating-Line-Info", NULL, 0, 0, NULL }, 722 { "NAS-IPv6-Address", NULL, 0, 0, print_attr_address6 }, 723 { "Framed-Interface-ID", NULL, 0, 0, NULL }, 724 { "Framed-IPv6-Prefix", NULL, 0, 0, print_attr_netmask6 }, 725 { "Login-IPv6-Host", NULL, 0, 0, print_attr_address6 }, 726 { "Framed-IPv6-Route", NULL, 0, 0, print_attr_string }, 727 /* ^ [90, 99] ^ */ 728 { "Framed-IPv6-Pool", NULL, 0, 0, print_attr_string }, 729 { "Error-Cause", NULL, 0, 0, print_attr_strange }, 730 { "EAP-Key-Name", NULL, 0, 0, NULL }, 731 { "Digest-Response", NULL, 0, 0, print_attr_string }, 732 { "Digest-Realm", NULL, 0, 0, print_attr_string }, 733 { "Digest-Nonce", NULL, 0, 0, print_attr_string }, 734 { "Digest-Response-Auth", NULL, 0, 0, print_attr_string }, 735 { "Digest-Nextnonce", NULL, 0, 0, print_attr_string }, 736 { "Digest-Method", NULL, 0, 0, print_attr_string }, 737 { "Digest-URI", NULL, 0, 0, print_attr_string }, 738 /* ^ [100, 109] ^ */ 739 { "Digest-Qop", NULL, 0, 0, print_attr_string }, 740 { "Digest-Algorithm", NULL, 0, 0, print_attr_string }, 741 { "Digest-Entity-Body-Hash", NULL, 0, 0, print_attr_string }, 742 { "Digest-CNonce", NULL, 0, 0, print_attr_string }, 743 { "Digest-Nonce-Count", NULL, 0, 0, print_attr_string }, 744 { "Digest-Username", NULL, 0, 0, print_attr_string }, 745 { "Digest-Opaque", NULL, 0, 0, print_attr_string }, 746 { "Digest-Auth-Param", NULL, 0, 0, print_attr_string }, 747 { "Digest-AKA-Auts", NULL, 0, 0, print_attr_string }, 748 { "Digest-Domain", NULL, 0, 0, print_attr_string }, 749 /* ^ [110, 119] ^ */ 750 { "Digest-Stale", NULL, 0, 0, print_attr_string }, 751 { "Digest-HA1", NULL, 0, 0, print_attr_string }, 752 { "SIP-AOR", NULL, 0, 0, print_attr_string }, 753 { "Delegated-IPv6-Prefix", NULL, 0, 0, print_attr_netmask6 }, 754 { "MIP6-Feature-Vector", NULL, 0, 0, print_attr_vector64 }, 755 { "MIP6-Home-Link-Prefix", NULL, 0, 0, print_attr_mip6_home_link_prefix }, 756 { "Operator-Name", NULL, 0, 0, print_attr_operator_name }, 757 { "Location-Information", NULL, 0, 0, print_attr_location_information }, 758 { "Location-Data", NULL, 0, 0, print_attr_location_data }, 759 { "Basic-Location-Policy-Rules", NULL, 0, 0, print_basic_location_policy_rules } 760 /* ^ [120, 129] ^ */ 761 }; 762 763 764 /*****************************/ 765 /* Print an attribute string */ 766 /* value pointed by 'data' */ 767 /* and 'length' size. */ 768 /*****************************/ 769 /* Returns nothing. */ 770 /*****************************/ 771 static void 772 print_attr_string(netdissect_options *ndo, 773 const u_char *data, u_int length, u_short attr_code) 774 { 775 u_int i; 776 777 ND_TCHECK_LEN(data, length); 778 779 switch(attr_code) { 780 case TUNNEL_PASS: 781 if (length < 3) 782 goto trunc; 783 if (GET_U_1(data) && (GET_U_1(data) <= 0x1F)) 784 ND_PRINT("Tag[%u] ", GET_U_1(data)); 785 else 786 ND_PRINT("Tag[Unused] "); 787 data++; 788 length--; 789 ND_PRINT("Salt %u ", GET_BE_U_2(data)); 790 data+=2; 791 length-=2; 792 break; 793 case TUNNEL_CLIENT_END: 794 case TUNNEL_SERVER_END: 795 case TUNNEL_PRIV_GROUP: 796 case TUNNEL_ASSIGN_ID: 797 case TUNNEL_CLIENT_AUTH: 798 case TUNNEL_SERVER_AUTH: 799 if (GET_U_1(data) <= 0x1F) { 800 if (length < 1) 801 goto trunc; 802 if (GET_U_1(data)) 803 ND_PRINT("Tag[%u] ", GET_U_1(data)); 804 else 805 ND_PRINT("Tag[Unused] "); 806 data++; 807 length--; 808 } 809 break; 810 case EGRESS_VLAN_NAME: 811 if (length < 1) 812 goto trunc; 813 ND_PRINT("%s (0x%02x) ", 814 tok2str(rfc4675_tagged,"Unknown tag",GET_U_1(data)), 815 GET_U_1(data)); 816 data++; 817 length--; 818 break; 819 case EAP_MESSAGE: 820 if (length < 1) 821 goto trunc; 822 eap_print(ndo, data, length); 823 return; 824 } 825 826 for (i=0; i < length && GET_U_1(data); i++, data++) 827 ND_PRINT("%c", ND_ASCII_ISPRINT(GET_U_1(data)) ? GET_U_1(data) : '.'); 828 829 return; 830 831 trunc: 832 nd_print_trunc(ndo); 833 } 834 835 /* 836 * print vendor specific attributes 837 */ 838 static void 839 print_vendor_attr(netdissect_options *ndo, 840 const u_char *data, u_int length, u_short attr_code _U_) 841 { 842 u_int idx; 843 u_int vendor_id; 844 u_int vendor_type; 845 u_int vendor_length; 846 847 if (length < 4) 848 goto trunc; 849 vendor_id = GET_BE_U_4(data); 850 data+=4; 851 length-=4; 852 853 ND_PRINT("Vendor: %s (%u)", 854 tok2str(smi_values,"Unknown",vendor_id), 855 vendor_id); 856 857 while (length >= 2) { 858 vendor_type = GET_U_1(data); 859 vendor_length = GET_U_1(data + 1); 860 861 if (vendor_length < 2) { 862 ND_PRINT("\n\t Vendor Attribute: %u, Length: %u (bogus, must be >= 2)", 863 vendor_type, 864 vendor_length); 865 return; 866 } 867 if (vendor_length > length) { 868 ND_PRINT("\n\t Vendor Attribute: %u, Length: %u (bogus, goes past end of vendor-specific attribute)", 869 vendor_type, 870 vendor_length); 871 return; 872 } 873 data+=2; 874 vendor_length-=2; 875 length-=2; 876 ND_TCHECK_LEN(data, vendor_length); 877 878 ND_PRINT("\n\t Vendor Attribute: %u, Length: %u, Value: ", 879 vendor_type, 880 vendor_length); 881 for (idx = 0; idx < vendor_length ; idx++, data++) 882 ND_PRINT("%c", ND_ASCII_ISPRINT(GET_U_1(data)) ? GET_U_1(data) : '.'); 883 length-=vendor_length; 884 } 885 return; 886 887 trunc: 888 nd_print_trunc(ndo); 889 } 890 891 /******************************/ 892 /* Print an attribute numeric */ 893 /* value pointed by 'data' */ 894 /* and 'length' size. */ 895 /******************************/ 896 /* Returns nothing. */ 897 /******************************/ 898 static void 899 print_attr_num(netdissect_options *ndo, 900 const u_char *data, u_int length, u_short attr_code) 901 { 902 uint32_t timeout; 903 904 if (length != 4) { 905 ND_PRINT("ERROR: length %u != 4", length); 906 return; 907 } 908 909 /* This attribute has standard values */ 910 if (attr_type[attr_code].siz_subtypes) { 911 static const char **table; 912 uint32_t data_value; 913 table = attr_type[attr_code].subtypes; 914 915 if ( (attr_code == TUNNEL_TYPE) || (attr_code == TUNNEL_MEDIUM) ) { 916 if (!GET_U_1(data)) 917 ND_PRINT("Tag[Unused] "); 918 else 919 ND_PRINT("Tag[%u] ", GET_U_1(data)); 920 data++; 921 data_value = GET_BE_U_3(data); 922 } else { 923 data_value = GET_BE_U_4(data); 924 } 925 if ( data_value <= (uint32_t)(attr_type[attr_code].siz_subtypes - 1 + 926 attr_type[attr_code].first_subtype) && 927 data_value >= attr_type[attr_code].first_subtype ) 928 ND_PRINT("%s", table[data_value]); 929 else 930 ND_PRINT("#%u", data_value); 931 } else { 932 switch(attr_code) /* Be aware of special cases... */ 933 { 934 case FRM_IPX: 935 if (GET_BE_U_4(data) == 0xFFFFFFFE ) 936 ND_PRINT("NAS Select"); 937 else 938 ND_PRINT("%u", GET_BE_U_4(data)); 939 break; 940 941 case SESSION_TIMEOUT: 942 case IDLE_TIMEOUT: 943 case ACCT_DELAY: 944 case ACCT_SESSION_TIME: 945 case ACCT_INT_INTERVAL: 946 timeout = GET_BE_U_4(data); 947 if ( timeout < 60 ) 948 ND_PRINT("%02d secs", timeout); 949 else { 950 if ( timeout < 3600 ) 951 ND_PRINT("%02d:%02d min", 952 timeout / 60, timeout % 60); 953 else 954 ND_PRINT("%02d:%02d:%02d hours", 955 timeout / 3600, (timeout % 3600) / 60, 956 timeout % 60); 957 } 958 break; 959 960 case FRM_ATALK_LINK: 961 if (GET_BE_U_4(data)) 962 ND_PRINT("%u", GET_BE_U_4(data)); 963 else 964 ND_PRINT("Unnumbered"); 965 break; 966 967 case FRM_ATALK_NETWORK: 968 if (GET_BE_U_4(data)) 969 ND_PRINT("%u", GET_BE_U_4(data)); 970 else 971 ND_PRINT("NAS assigned"); 972 break; 973 974 case TUNNEL_PREFERENCE: 975 if (GET_U_1(data)) 976 ND_PRINT("Tag[%u] ", GET_U_1(data)); 977 else 978 ND_PRINT("Tag[Unused] "); 979 data++; 980 ND_PRINT("%u", GET_BE_U_3(data)); 981 break; 982 983 case EGRESS_VLAN_ID: 984 ND_PRINT("%s (0x%02x) ", 985 tok2str(rfc4675_tagged,"Unknown tag",GET_U_1(data)), 986 GET_U_1(data)); 987 data++; 988 ND_PRINT("%u", GET_BE_U_3(data)); 989 break; 990 991 default: 992 ND_PRINT("%u", GET_BE_U_4(data)); 993 break; 994 995 } /* switch */ 996 997 } /* if-else */ 998 } 999 1000 /*****************************/ 1001 /* Print an attribute IPv4 */ 1002 /* address value pointed by */ 1003 /* 'data' and 'length' size. */ 1004 /*****************************/ 1005 /* Returns nothing. */ 1006 /*****************************/ 1007 static void 1008 print_attr_address(netdissect_options *ndo, 1009 const u_char *data, u_int length, u_short attr_code) 1010 { 1011 if (length != 4) { 1012 ND_PRINT("ERROR: length %u != 4", length); 1013 return; 1014 } 1015 1016 switch(attr_code) { 1017 case FRM_IPADDR: 1018 case LOG_IPHOST: 1019 if (GET_BE_U_4(data) == 0xFFFFFFFF ) 1020 ND_PRINT("User Selected"); 1021 else 1022 if (GET_BE_U_4(data) == 0xFFFFFFFE ) 1023 ND_PRINT("NAS Select"); 1024 else 1025 ND_PRINT("%s",GET_IPADDR_STRING(data)); 1026 break; 1027 1028 default: 1029 ND_PRINT("%s", GET_IPADDR_STRING(data)); 1030 break; 1031 } 1032 } 1033 1034 /*****************************/ 1035 /* Print an attribute IPv6 */ 1036 /* address value pointed by */ 1037 /* 'data' and 'length' size. */ 1038 /*****************************/ 1039 /* Returns nothing. */ 1040 /*****************************/ 1041 static void 1042 print_attr_address6(netdissect_options *ndo, 1043 const u_char *data, u_int length, u_short attr_code _U_) 1044 { 1045 if (length != 16) { 1046 ND_PRINT("ERROR: length %u != 16", length); 1047 return; 1048 } 1049 1050 ND_PRINT("%s", GET_IP6ADDR_STRING(data)); 1051 } 1052 1053 static void 1054 print_attr_netmask6(netdissect_options *ndo, 1055 const u_char *data, u_int length, u_short attr_code _U_) 1056 { 1057 u_char data2[16]; 1058 1059 if (length < 2 || length > 18) { 1060 ND_PRINT("ERROR: length %u not in range (2..18)", length); 1061 return; 1062 } 1063 ND_TCHECK_LEN(data, length); 1064 if (GET_U_1(data + 1) > 128) { 1065 ND_PRINT("ERROR: netmask %u not in range (0..128)", GET_U_1(data + 1)); 1066 return; 1067 } 1068 1069 memset(data2, 0, sizeof(data2)); 1070 if (length > 2) 1071 memcpy(data2, data+2, length-2); 1072 1073 ND_PRINT("%s/%u", ip6addr_string(ndo, data2), GET_U_1(data + 1)); /* local buffer, not packet data; don't use GET_IP6ADDR_STRING() */ 1074 1075 if (GET_U_1(data + 1) > 8 * (length - 2)) 1076 ND_PRINT(" (inconsistent prefix length)"); 1077 1078 return; 1079 1080 trunc: 1081 nd_print_trunc(ndo); 1082 } 1083 1084 static void 1085 print_attr_mip6_home_link_prefix(netdissect_options *ndo, 1086 const u_char *data, u_int length, u_short attr_code _U_) 1087 { 1088 if (length != 17) { 1089 ND_PRINT("ERROR: length %u != 17", length); 1090 return; 1091 } 1092 ND_TCHECK_LEN(data, length); 1093 if (GET_U_1(data) > 128) { 1094 ND_PRINT("ERROR: netmask %u not in range (0..128)", GET_U_1(data)); 1095 return; 1096 } 1097 1098 ND_PRINT("%s/%u", GET_IP6ADDR_STRING(data + 1), GET_U_1(data)); 1099 1100 return; 1101 1102 trunc: 1103 nd_print_trunc(ndo); 1104 } 1105 1106 static void 1107 print_attr_operator_name(netdissect_options *ndo, 1108 const u_char *data, u_int length, u_short attr_code _U_) 1109 { 1110 u_int namespace_value; 1111 1112 ND_TCHECK_LEN(data, length); 1113 if (length < 2) { 1114 ND_PRINT("ERROR: length %u < 2", length); 1115 return; 1116 } 1117 namespace_value = GET_U_1(data); 1118 data++; 1119 ND_PRINT("[%s] ", tok2str(operator_name_vector, "unknown namespace %u", namespace_value)); 1120 1121 (void)nd_printn(ndo, data, length - 1, NULL); 1122 1123 return; 1124 1125 trunc: 1126 nd_print_trunc(ndo); 1127 } 1128 1129 static void 1130 print_attr_location_information(netdissect_options *ndo, 1131 const u_char *data, u_int length, u_short attr_code _U_) 1132 { 1133 uint16_t index; 1134 uint8_t code, entity; 1135 1136 ND_TCHECK_LEN(data, length); 1137 if (length < 21) { 1138 ND_PRINT("ERROR: length %u < 21", length); 1139 return; 1140 } 1141 1142 index = GET_BE_U_2(data); 1143 data += 2; 1144 1145 code = GET_U_1(data); 1146 data++; 1147 1148 entity = GET_U_1(data); 1149 data++; 1150 1151 ND_PRINT("index %u, code %s, entity %s, ", 1152 index, 1153 tok2str(location_information_code_vector, "Unknown (%u)", code), 1154 tok2str(location_information_entity_vector, "Unknown (%u)", entity) 1155 ); 1156 1157 ND_PRINT("sighting time "); 1158 p_ntp_time(ndo, (const struct l_fixedpt *)data); 1159 ND_PRINT(", "); 1160 data += 8; 1161 1162 ND_PRINT("time to live "); 1163 p_ntp_time(ndo, (const struct l_fixedpt *)data); 1164 ND_PRINT(", "); 1165 data += 8; 1166 1167 ND_PRINT("method \""); 1168 (void)nd_printn(ndo, data, length - 20, NULL); 1169 ND_PRINT("\""); 1170 1171 return; 1172 1173 trunc: 1174 nd_print_trunc(ndo); 1175 } 1176 1177 static void 1178 print_attr_location_data(netdissect_options *ndo, 1179 const u_char *data, u_int length, u_short attr_code _U_) 1180 { 1181 uint16_t index; 1182 1183 ND_TCHECK_LEN(data, length); 1184 if (length < 3) { 1185 ND_PRINT("ERROR: length %u < 3", length); 1186 return; 1187 } 1188 1189 index = GET_BE_U_2(data); 1190 data += 2; 1191 ND_PRINT("index %u, location", index); 1192 1193 /* The Location field of the String field of the Location-Data attribute 1194 * can have two completely different structures depending on the value of 1195 * the Code field of a Location-Info attribute, which supposedly precedes 1196 * the current attribute. Unfortunately, this choice of encoding makes it 1197 * non-trivial to decode the Location field without preserving some state 1198 * between the attributes. 1199 */ 1200 hex_and_ascii_print(ndo, "\n\t ", data, length - 2); 1201 1202 return; 1203 1204 trunc: 1205 nd_print_trunc(ndo); 1206 } 1207 1208 static void 1209 print_basic_location_policy_rules(netdissect_options *ndo, 1210 const u_char *data, u_int length, u_short attr_code _U_) 1211 { 1212 uint16_t flags; 1213 1214 ND_TCHECK_LEN(data, length); 1215 if (length < 10) { 1216 ND_PRINT("ERROR: length %u < 10", length); 1217 return; 1218 } 1219 1220 flags = GET_BE_U_2(data); 1221 data += 2; 1222 ND_PRINT("flags [%s], ", bittok2str(blpr_bm, "none", flags)); 1223 1224 ND_PRINT("retention expires "); 1225 p_ntp_time(ndo, (const struct l_fixedpt *)data); 1226 data += 8; 1227 1228 if (length > 10) { 1229 ND_PRINT(", note well \""); 1230 (void)nd_printn(ndo, data, length - 10, NULL); 1231 ND_PRINT("\""); 1232 } 1233 1234 return; 1235 1236 trunc: 1237 nd_print_trunc(ndo); 1238 } 1239 1240 1241 /*************************************/ 1242 /* Print an attribute of 'secs since */ 1243 /* January 1, 1970 00:00 UTC' value */ 1244 /* pointed by 'data' and 'length' */ 1245 /* size. */ 1246 /*************************************/ 1247 /* Returns nothing. */ 1248 /*************************************/ 1249 static void 1250 print_attr_time(netdissect_options *ndo, 1251 const u_char *data, u_int length, u_short attr_code _U_) 1252 { 1253 time_t attr_time; 1254 char string[26]; 1255 1256 if (length != 4) { 1257 ND_PRINT("ERROR: length %u != 4", length); 1258 return; 1259 } 1260 1261 attr_time = GET_BE_U_4(data); 1262 strlcpy(string, ctime(&attr_time), sizeof(string)); 1263 /* Get rid of the newline */ 1264 string[24] = '\0'; 1265 ND_PRINT("%.24s", string); 1266 } 1267 1268 static void 1269 print_attr_vector64(netdissect_options *ndo, 1270 const u_char *data, u_int length, u_short attr_code _U_) 1271 { 1272 uint64_t data_value, i; 1273 const char *sep = ""; 1274 1275 if (length != 8) { 1276 ND_PRINT("ERROR: length %u != 8", length); 1277 return; 1278 } 1279 1280 ND_PRINT("["); 1281 1282 data_value = GET_BE_U_8(data); 1283 /* Print the 64-bit field in a format similar to bittok2str(), less 1284 * flagging any unknown bits. This way it should be easier to replace 1285 * the custom code with a library function later. 1286 */ 1287 for (i = 0; i < TAM_SIZE(mip6_feature_vector); i++) { 1288 if (data_value & mip6_feature_vector[i].v) { 1289 ND_PRINT("%s%s", sep, mip6_feature_vector[i].s); 1290 sep = ", "; 1291 } 1292 } 1293 1294 ND_PRINT("]"); 1295 } 1296 1297 /***********************************/ 1298 /* Print an attribute of 'strange' */ 1299 /* data format pointed by 'data' */ 1300 /* and 'length' size. */ 1301 /***********************************/ 1302 /* Returns nothing. */ 1303 /***********************************/ 1304 static void 1305 print_attr_strange(netdissect_options *ndo, 1306 const u_char *data, u_int length, u_short attr_code) 1307 { 1308 u_short len_data; 1309 u_int error_cause_value; 1310 1311 switch(attr_code) { 1312 case ARAP_PASS: 1313 if (length != 16) { 1314 ND_PRINT("ERROR: length %u != 16", length); 1315 return; 1316 } 1317 ND_PRINT("User_challenge ("); 1318 len_data = 8; 1319 PRINT_HEX(len_data, data); 1320 ND_PRINT(") User_resp("); 1321 len_data = 8; 1322 PRINT_HEX(len_data, data); 1323 ND_PRINT(")"); 1324 break; 1325 1326 case ARAP_FEATURES: 1327 if (length != 14) { 1328 ND_PRINT("ERROR: length %u != 14", length); 1329 return; 1330 } 1331 if (GET_U_1(data)) 1332 ND_PRINT("User can change password"); 1333 else 1334 ND_PRINT("User cannot change password"); 1335 data++; 1336 ND_PRINT(", Min password length: %u", GET_U_1(data)); 1337 data++; 1338 ND_PRINT(", created at: "); 1339 len_data = 4; 1340 PRINT_HEX(len_data, data); 1341 ND_PRINT(", expires in: "); 1342 len_data = 4; 1343 PRINT_HEX(len_data, data); 1344 ND_PRINT(", Current Time: "); 1345 len_data = 4; 1346 PRINT_HEX(len_data, data); 1347 break; 1348 1349 case ARAP_CHALLENGE_RESP: 1350 if (length < 8) { 1351 ND_PRINT("ERROR: length %u != 8", length); 1352 return; 1353 } 1354 len_data = 8; 1355 PRINT_HEX(len_data, data); 1356 break; 1357 1358 case ERROR_CAUSE: 1359 if (length != 4) { 1360 ND_PRINT("Error: length %u != 4", length); 1361 return; 1362 } 1363 1364 error_cause_value = GET_BE_U_4(data); 1365 ND_PRINT("Error cause %u: %s", error_cause_value, tok2str(errorcausetype, "Error-Cause %u not known", error_cause_value)); 1366 break; 1367 } 1368 return; 1369 } 1370 1371 static void 1372 radius_attrs_print(netdissect_options *ndo, 1373 const u_char *attr, u_int length) 1374 { 1375 const struct radius_attr *rad_attr = (const struct radius_attr *)attr; 1376 const char *attr_string; 1377 uint8_t type, len; 1378 1379 while (length > 0) { 1380 if (length < 2) 1381 goto trunc; 1382 ND_TCHECK_SIZE(rad_attr); 1383 1384 type = GET_U_1(rad_attr->type); 1385 len = GET_U_1(rad_attr->len); 1386 if (type != 0 && type < TAM_SIZE(attr_type)) 1387 attr_string = attr_type[type].name; 1388 else 1389 attr_string = "Unknown"; 1390 1391 ND_PRINT("\n\t %s Attribute (%u), length: %u", 1392 attr_string, 1393 type, 1394 len); 1395 if (len < 2) { 1396 ND_PRINT(" (bogus, must be >= 2)"); 1397 return; 1398 } 1399 if (len > length) { 1400 ND_PRINT(" (bogus, goes past end of packet)"); 1401 return; 1402 } 1403 ND_PRINT(", Value: "); 1404 1405 if (type < TAM_SIZE(attr_type)) { 1406 if (len > 2) { 1407 if ( attr_type[type].print_func ) 1408 (*attr_type[type].print_func)( 1409 ndo, ((const u_char *)(rad_attr+1)), 1410 len - 2, type); 1411 } 1412 } 1413 /* do we also want to see a hex dump ? */ 1414 if (ndo->ndo_vflag> 1) 1415 print_unknown_data(ndo, (const u_char *)rad_attr+2, "\n\t ", (len)-2); 1416 1417 length-=(len); 1418 rad_attr = (const struct radius_attr *)( ((const char *)(rad_attr))+len); 1419 } 1420 return; 1421 1422 trunc: 1423 nd_print_trunc(ndo); 1424 } 1425 1426 void 1427 radius_print(netdissect_options *ndo, 1428 const u_char *dat, u_int length) 1429 { 1430 const struct radius_hdr *rad; 1431 u_int len, auth_idx; 1432 1433 ndo->ndo_protocol = "radius"; 1434 ND_TCHECK_LEN(dat, MIN_RADIUS_LEN); 1435 rad = (const struct radius_hdr *)dat; 1436 len = GET_BE_U_2(rad->len); 1437 1438 if (len < MIN_RADIUS_LEN) { 1439 nd_print_trunc(ndo); 1440 return; 1441 } 1442 1443 if (len > length) 1444 len = length; 1445 1446 if (ndo->ndo_vflag < 1) { 1447 ND_PRINT("RADIUS, %s (%u), id: 0x%02x length: %u", 1448 tok2str(radius_command_values,"Unknown Command",GET_U_1(rad->code)), 1449 GET_U_1(rad->code), 1450 GET_U_1(rad->id), 1451 len); 1452 return; 1453 } else { 1454 ND_PRINT("RADIUS, length: %u\n\t%s (%u), id: 0x%02x, Authenticator: ", 1455 len, 1456 tok2str(radius_command_values,"Unknown Command",GET_U_1(rad->code)), 1457 GET_U_1(rad->code), 1458 GET_U_1(rad->id)); 1459 1460 for(auth_idx=0; auth_idx < 16; auth_idx++) 1461 ND_PRINT("%02x", rad->auth[auth_idx]); 1462 } 1463 1464 if (len > MIN_RADIUS_LEN) 1465 radius_attrs_print(ndo, dat + MIN_RADIUS_LEN, len - MIN_RADIUS_LEN); 1466 return; 1467 1468 trunc: 1469 nd_print_trunc(ndo); 1470 } 1471