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