xref: /netbsd-src/external/bsd/tcpdump/dist/print-radius.c (revision 26ba0b503b498a5194a71ac319838b7f5497f3fe)
10f74e101Schristos /*
20f74e101Schristos  * Copyright (C) 2000 Alfredo Andres Omella.  All rights reserved.
30f74e101Schristos  *
40f74e101Schristos  * Redistribution and use in source and binary forms, with or without
50f74e101Schristos  * modification, are permitted provided that the following conditions
60f74e101Schristos  * are met:
70f74e101Schristos  *
80f74e101Schristos  *   1. Redistributions of source code must retain the above copyright
90f74e101Schristos  *      notice, this list of conditions and the following disclaimer.
100f74e101Schristos  *   2. Redistributions in binary form must reproduce the above copyright
110f74e101Schristos  *      notice, this list of conditions and the following disclaimer in
120f74e101Schristos  *      the documentation and/or other materials provided with the
130f74e101Schristos  *      distribution.
140f74e101Schristos  *   3. The names of the authors may not be used to endorse or promote
150f74e101Schristos  *      products derived from this software without specific prior
160f74e101Schristos  *      written permission.
170f74e101Schristos  *
180f74e101Schristos  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
190f74e101Schristos  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
200f74e101Schristos  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
210f74e101Schristos  */
22dc860a36Sspz 
23dc860a36Sspz /* \summary: Radius protocol printer */
24dc860a36Sspz 
250f74e101Schristos /*
260f74e101Schristos  * Radius printer routines as specified on:
270f74e101Schristos  *
280f74e101Schristos  * RFC 2865:
290f74e101Schristos  *      "Remote Authentication Dial In User Service (RADIUS)"
300f74e101Schristos  *
310f74e101Schristos  * RFC 2866:
320f74e101Schristos  *      "RADIUS Accounting"
330f74e101Schristos  *
340f74e101Schristos  * RFC 2867:
350f74e101Schristos  *      "RADIUS Accounting Modifications for Tunnel Protocol Support"
360f74e101Schristos  *
370f74e101Schristos  * RFC 2868:
380f74e101Schristos  *      "RADIUS Attributes for Tunnel Protocol Support"
390f74e101Schristos  *
400f74e101Schristos  * RFC 2869:
410f74e101Schristos  *      "RADIUS Extensions"
420f74e101Schristos  *
43c74ad251Schristos  * RFC 3162:
44c74ad251Schristos  *      "RADIUS and IPv6"
45c74ad251Schristos  *
46fdccd7e4Schristos  * RFC 3580:
47fdccd7e4Schristos  *      "IEEE 802.1X Remote Authentication Dial In User Service (RADIUS)"
48fdccd7e4Schristos  *      "Usage Guidelines"
49fdccd7e4Schristos  *
50c74ad251Schristos  * RFC 4072:
51c74ad251Schristos  *      "Diameter Extensible Authentication Protocol (EAP) Application"
52c74ad251Schristos  *
53ba2ff121Schristos  * RFC 4675:
54ba2ff121Schristos  *      "RADIUS Attributes for Virtual LAN and Priority Support"
55ba2ff121Schristos  *
56c74ad251Schristos  * RFC 4818:
57c74ad251Schristos  *      "RADIUS Delegated-IPv6-Prefix Attribute"
58c74ad251Schristos  *
59c74ad251Schristos  * RFC 4849:
60c74ad251Schristos  *      "RADIUS Filter Rule Attribute"
61c74ad251Schristos  *
62c74ad251Schristos  * RFC 5090:
63c74ad251Schristos  *      "RADIUS Extension for Digest Authentication"
64c74ad251Schristos  *
65ba2ff121Schristos  * RFC 5176:
66ba2ff121Schristos  *      "Dynamic Authorization Extensions to RADIUS"
67ba2ff121Schristos  *
68c74ad251Schristos  * RFC 5447:
69c74ad251Schristos  *      "Diameter Mobile IPv6"
70c74ad251Schristos  *
71c74ad251Schristos  * RFC 5580:
72c74ad251Schristos  *      "Carrying Location Objects in RADIUS and Diameter"
73c74ad251Schristos  *
74c74ad251Schristos  * RFC 6572:
75c74ad251Schristos  *      "RADIUS Support for Proxy Mobile IPv6"
76c74ad251Schristos  *
77c74ad251Schristos  * RFC 7155:
78c74ad251Schristos  *      "Diameter Network Access Server Application"
79c74ad251Schristos  *
800f74e101Schristos  * Alfredo Andres Omella (aandres@s21sec.com) v0.1 2000/09/15
810f74e101Schristos  *
820f74e101Schristos  * TODO: Among other things to print ok MacIntosh and Vendor values
830f74e101Schristos  */
840f74e101Schristos 
85fdccd7e4Schristos #include <sys/cdefs.h>
86fdccd7e4Schristos #ifndef lint
87*26ba0b50Schristos __RCSID("$NetBSD: print-radius.c,v 1.11 2024/09/02 16:15:32 christos Exp $");
88fdccd7e4Schristos #endif
89fdccd7e4Schristos 
90c74ad251Schristos #include <config.h>
910f74e101Schristos 
92c74ad251Schristos #include "netdissect-stdinc.h"
930f74e101Schristos 
940f74e101Schristos #include <string.h>
950f74e101Schristos 
96c74ad251Schristos #include "netdissect-ctype.h"
97c74ad251Schristos 
98fdccd7e4Schristos #include "netdissect.h"
990f74e101Schristos #include "addrtoname.h"
1000f74e101Schristos #include "extract.h"
1010f74e101Schristos #include "oui.h"
102c74ad251Schristos #include "ntp.h"
1030f74e101Schristos 
104b3a00663Schristos 
1050f74e101Schristos #define TAM_SIZE(x) (sizeof(x)/sizeof(x[0]) )
1060f74e101Schristos 
1070f74e101Schristos #define PRINT_HEX(bytes_len, ptr_data)                               \
1080f74e101Schristos            while(bytes_len)                                          \
1090f74e101Schristos            {                                                         \
110c74ad251Schristos               ND_PRINT("%02X", GET_U_1(ptr_data));                   \
1110f74e101Schristos               ptr_data++;                                            \
1120f74e101Schristos               bytes_len--;                                           \
1130f74e101Schristos            }
1140f74e101Schristos 
1150f74e101Schristos 
1160f74e101Schristos /* Radius packet codes */
117c74ad251Schristos /* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-27 */
1180f74e101Schristos #define RADCMD_ACCESS_REQ    1 /* Access-Request      */
1190f74e101Schristos #define RADCMD_ACCESS_ACC    2 /* Access-Accept       */
1200f74e101Schristos #define RADCMD_ACCESS_REJ    3 /* Access-Reject       */
121*26ba0b50Schristos #define RADCMD_ACCOUNT_REQ   4 /* Accounting-Request  */
122*26ba0b50Schristos #define RADCMD_ACCOUNT_RES   5 /* Accounting-Response */
1230f74e101Schristos #define RADCMD_ACCESS_CHA   11 /* Access-Challenge    */
1240f74e101Schristos #define RADCMD_STATUS_SER   12 /* Status-Server       */
1250f74e101Schristos #define RADCMD_STATUS_CLI   13 /* Status-Client       */
126ba2ff121Schristos #define RADCMD_DISCON_REQ   40 /* Disconnect-Request  */
127ba2ff121Schristos #define RADCMD_DISCON_ACK   41 /* Disconnect-ACK      */
128ba2ff121Schristos #define RADCMD_DISCON_NAK   42 /* Disconnect-NAK      */
129ba2ff121Schristos #define RADCMD_COA_REQ      43 /* CoA-Request         */
130ba2ff121Schristos #define RADCMD_COA_ACK      44 /* CoA-ACK             */
131ba2ff121Schristos #define RADCMD_COA_NAK      45 /* CoA-NAK             */
1320f74e101Schristos #define RADCMD_RESERVED    255 /* Reserved            */
1330f74e101Schristos 
134870189d2Schristos static const struct tok radius_command_values[] = {
135ba2ff121Schristos     { RADCMD_ACCESS_REQ,  "Access-Request" },
136ba2ff121Schristos     { RADCMD_ACCESS_ACC,  "Access-Accept" },
137ba2ff121Schristos     { RADCMD_ACCESS_REJ,  "Access-Reject" },
138*26ba0b50Schristos     { RADCMD_ACCOUNT_REQ, "Accounting-Request" },
139*26ba0b50Schristos     { RADCMD_ACCOUNT_RES, "Accounting-Response" },
140ba2ff121Schristos     { RADCMD_ACCESS_CHA,  "Access-Challenge" },
141ba2ff121Schristos     { RADCMD_STATUS_SER,  "Status-Server" },
142ba2ff121Schristos     { RADCMD_STATUS_CLI,  "Status-Client" },
143ba2ff121Schristos     { RADCMD_DISCON_REQ,  "Disconnect-Request" },
144ba2ff121Schristos     { RADCMD_DISCON_ACK,  "Disconnect-ACK" },
145ba2ff121Schristos     { RADCMD_DISCON_NAK,  "Disconnect-NAK" },
146ba2ff121Schristos     { RADCMD_COA_REQ,     "CoA-Request" },
147ba2ff121Schristos     { RADCMD_COA_ACK,     "CoA-ACK" },
148ba2ff121Schristos     { RADCMD_COA_NAK,     "CoA-NAK" },
1490f74e101Schristos     { RADCMD_RESERVED,    "Reserved" },
1500f74e101Schristos     { 0, NULL}
1510f74e101Schristos };
1520f74e101Schristos 
1530f74e101Schristos /********************************/
1540f74e101Schristos /* Begin Radius Attribute types */
1550f74e101Schristos /********************************/
1560f74e101Schristos #define SERV_TYPE    6
1570f74e101Schristos #define FRM_IPADDR   8
1580f74e101Schristos #define LOG_IPHOST  14
1590f74e101Schristos #define LOG_SERVICE 15
1600f74e101Schristos #define FRM_IPX     23
1610f74e101Schristos #define SESSION_TIMEOUT   27
1620f74e101Schristos #define IDLE_TIMEOUT      28
1630f74e101Schristos #define FRM_ATALK_LINK    37
1640f74e101Schristos #define FRM_ATALK_NETWORK 38
1650f74e101Schristos 
1660f74e101Schristos #define ACCT_DELAY        41
1670f74e101Schristos #define ACCT_SESSION_TIME 46
1680f74e101Schristos 
169ba2ff121Schristos #define EGRESS_VLAN_ID   56
170ba2ff121Schristos #define EGRESS_VLAN_NAME 58
171ba2ff121Schristos 
1720f74e101Schristos #define TUNNEL_TYPE        64
1730f74e101Schristos #define TUNNEL_MEDIUM      65
1740f74e101Schristos #define TUNNEL_CLIENT_END  66
1750f74e101Schristos #define TUNNEL_SERVER_END  67
1760f74e101Schristos #define TUNNEL_PASS        69
1770f74e101Schristos 
1780f74e101Schristos #define ARAP_PASS          70
1790f74e101Schristos #define ARAP_FEATURES      71
1800f74e101Schristos 
181c74ad251Schristos #define EAP_MESSAGE        79
182c74ad251Schristos 
1830f74e101Schristos #define TUNNEL_PRIV_GROUP  81
1840f74e101Schristos #define TUNNEL_ASSIGN_ID   82
1850f74e101Schristos #define TUNNEL_PREFERENCE  83
1860f74e101Schristos 
1870f74e101Schristos #define ARAP_CHALLENGE_RESP 84
1880f74e101Schristos #define ACCT_INT_INTERVAL   85
1890f74e101Schristos 
1900f74e101Schristos #define TUNNEL_CLIENT_AUTH 90
1910f74e101Schristos #define TUNNEL_SERVER_AUTH 91
192c74ad251Schristos 
193c74ad251Schristos #define ERROR_CAUSE 101
1940f74e101Schristos /********************************/
1950f74e101Schristos /* End Radius Attribute types */
1960f74e101Schristos /********************************/
1970f74e101Schristos 
198ba2ff121Schristos #define RFC4675_TAGGED   0x31
199ba2ff121Schristos #define RFC4675_UNTAGGED 0x32
200ba2ff121Schristos 
201ba2ff121Schristos static const struct tok rfc4675_tagged[] = {
202ba2ff121Schristos     { RFC4675_TAGGED,   "Tagged" },
203ba2ff121Schristos     { RFC4675_UNTAGGED, "Untagged" },
204ba2ff121Schristos     { 0, NULL}
205ba2ff121Schristos };
206ba2ff121Schristos 
2070f74e101Schristos 
208c74ad251Schristos static void print_attr_string(netdissect_options *, const u_char *, u_int, u_short );
209c74ad251Schristos static void print_attr_num(netdissect_options *, const u_char *, u_int, u_short );
210c74ad251Schristos static void print_vendor_attr(netdissect_options *, const u_char *, u_int, u_short );
211c74ad251Schristos static void print_attr_address(netdissect_options *, const u_char *, u_int, u_short);
212c74ad251Schristos static void print_attr_address6(netdissect_options *, const u_char *, u_int, u_short);
213c74ad251Schristos static void print_attr_netmask6(netdissect_options *, const u_char *, u_int, u_short);
214c74ad251Schristos static void print_attr_mip6_home_link_prefix(netdissect_options *, const u_char *, u_int, u_short);
215c74ad251Schristos static void print_attr_operator_name(netdissect_options *, const u_char *, u_int, u_short);
216c74ad251Schristos static void print_attr_location_information(netdissect_options *, const u_char *, u_int, u_short);
217c74ad251Schristos static void print_attr_location_data(netdissect_options *, const u_char *, u_int, u_short);
218c74ad251Schristos static void print_basic_location_policy_rules(netdissect_options *, const u_char *, u_int, u_short);
219c74ad251Schristos static void print_attr_time(netdissect_options *, const u_char *, u_int, u_short);
220*26ba0b50Schristos static void print_attr_vector64(netdissect_options *, const u_char *, u_int, u_short);
221c74ad251Schristos static void print_attr_strange(netdissect_options *, const u_char *, u_int, u_short);
2220f74e101Schristos 
2230f74e101Schristos 
224c74ad251Schristos struct radius_hdr { nd_uint8_t  code;     /* Radius packet code  */
225c74ad251Schristos                     nd_uint8_t  id;       /* Radius packet id    */
226c74ad251Schristos                     nd_uint16_t len;      /* Radius total length */
227c74ad251Schristos                     nd_byte     auth[16]; /* Authenticator   */
2280f74e101Schristos                   };
2290f74e101Schristos 
2300f74e101Schristos #define MIN_RADIUS_LEN	20
2310f74e101Schristos 
232c74ad251Schristos struct radius_attr { nd_uint8_t type; /* Attribute type   */
233c74ad251Schristos                      nd_uint8_t len;  /* Attribute length */
2340f74e101Schristos                    };
2350f74e101Schristos 
2360f74e101Schristos 
2370f74e101Schristos /* Service-Type Attribute standard values */
238c74ad251Schristos /* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-4 */
2390f74e101Schristos static const char *serv_type[]={ NULL,
2400f74e101Schristos                                 "Login",
2410f74e101Schristos                                 "Framed",
2420f74e101Schristos                                 "Callback Login",
2430f74e101Schristos                                 "Callback Framed",
2440f74e101Schristos                                 "Outbound",
2450f74e101Schristos                                 "Administrative",
2460f74e101Schristos                                 "NAS Prompt",
2470f74e101Schristos                                 "Authenticate Only",
2480f74e101Schristos                                 "Callback NAS Prompt",
249c74ad251Schristos                                 /* ^ [0, 9] ^ */
2500f74e101Schristos                                 "Call Check",
2510f74e101Schristos                                 "Callback Administrative",
252c74ad251Schristos                                 "Voice",
253c74ad251Schristos                                 "Fax",
254c74ad251Schristos                                 "Modem Relay",
255c74ad251Schristos                                 "IAPP-Register",
256c74ad251Schristos                                 "IAPP-AP-Check",
257c74ad251Schristos                                 "Authorize Only",
258c74ad251Schristos                                 "Framed-Management",
259c74ad251Schristos                                 "Additional-Authorization",
260c74ad251Schristos                                 /* ^ [10, 19] ^ */
2610f74e101Schristos                                };
2620f74e101Schristos 
2630f74e101Schristos /* Framed-Protocol Attribute standard values */
264c74ad251Schristos /* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-5 */
2650f74e101Schristos static const char *frm_proto[]={ NULL,
2660f74e101Schristos                                  "PPP",
2670f74e101Schristos                                  "SLIP",
2680f74e101Schristos                                  "ARAP",
2690f74e101Schristos                                  "Gandalf proprietary",
2700f74e101Schristos                                  "Xylogics IPX/SLIP",
2710f74e101Schristos                                  "X.75 Synchronous",
272c74ad251Schristos                                  "GPRS PDP Context",
2730f74e101Schristos                                };
2740f74e101Schristos 
2750f74e101Schristos /* Framed-Routing Attribute standard values */
276c74ad251Schristos /* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-6 */
2770f74e101Schristos static const char *frm_routing[]={ "None",
2780f74e101Schristos                                    "Send",
2790f74e101Schristos                                    "Listen",
2800f74e101Schristos                                    "Send&Listen",
2810f74e101Schristos                                  };
2820f74e101Schristos 
2830f74e101Schristos /* Framed-Compression Attribute standard values */
284c74ad251Schristos /* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-7 */
2850f74e101Schristos static const char *frm_comp[]={ "None",
2860f74e101Schristos                                 "VJ TCP/IP",
2870f74e101Schristos                                 "IPX",
2880f74e101Schristos                                 "Stac-LZS",
2890f74e101Schristos                               };
2900f74e101Schristos 
2910f74e101Schristos /* Login-Service Attribute standard values */
292c74ad251Schristos /* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-8 */
2930f74e101Schristos static const char *login_serv[]={ "Telnet",
2940f74e101Schristos                                   "Rlogin",
2950f74e101Schristos                                   "TCP Clear",
2960f74e101Schristos                                   "PortMaster(proprietary)",
2970f74e101Schristos                                   "LAT",
2980f74e101Schristos                                   "X.25-PAD",
2990f74e101Schristos                                   "X.25-T3POS",
3000f74e101Schristos                                   "Unassigned",
3010f74e101Schristos                                   "TCP Clear Quiet",
3020f74e101Schristos                                 };
3030f74e101Schristos 
3040f74e101Schristos 
3050f74e101Schristos /* Termination-Action Attribute standard values */
306c74ad251Schristos /* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-9 */
3070f74e101Schristos static const char *term_action[]={ "Default",
3080f74e101Schristos                                    "RADIUS-Request",
3090f74e101Schristos                                  };
3100f74e101Schristos 
311ba2ff121Schristos /* Ingress-Filters Attribute standard values */
312ba2ff121Schristos static const char *ingress_filters[]={ NULL,
313ba2ff121Schristos                                        "Enabled",
314ba2ff121Schristos                                        "Disabled",
315ba2ff121Schristos                                      };
316ba2ff121Schristos 
3170f74e101Schristos /* NAS-Port-Type Attribute standard values */
318c74ad251Schristos /* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-13 */
3190f74e101Schristos static const char *nas_port_type[]={ "Async",
3200f74e101Schristos                                      "Sync",
3210f74e101Schristos                                      "ISDN Sync",
3220f74e101Schristos                                      "ISDN Async V.120",
3230f74e101Schristos                                      "ISDN Async V.110",
3240f74e101Schristos                                      "Virtual",
3250f74e101Schristos                                      "PIAFS",
3260f74e101Schristos                                      "HDLC Clear Channel",
3270f74e101Schristos                                      "X.25",
3280f74e101Schristos                                      "X.75",
329c74ad251Schristos                                      /* ^ [0, 9] ^ */
3300f74e101Schristos                                      "G.3 Fax",
3310f74e101Schristos                                      "SDSL",
3320f74e101Schristos                                      "ADSL-CAP",
3330f74e101Schristos                                      "ADSL-DMT",
3340f74e101Schristos                                      "ISDN-DSL",
3350f74e101Schristos                                      "Ethernet",
3360f74e101Schristos                                      "xDSL",
3370f74e101Schristos                                      "Cable",
3380f74e101Schristos                                      "Wireless - Other",
3390f74e101Schristos                                      "Wireless - IEEE 802.11",
340c74ad251Schristos                                      /* ^ [10, 19] ^ */
341c74ad251Schristos                                      "Token-Ring",
342c74ad251Schristos                                      "FDDI",
343c74ad251Schristos                                      "Wireless - CDMA200",
344c74ad251Schristos                                      "Wireless - UMTS",
345c74ad251Schristos                                      "Wireless - 1X-EV",
346c74ad251Schristos                                      "IAPP",
347c74ad251Schristos                                      "FTTP",
348c74ad251Schristos                                      "Wireless - IEEE 802.16",
349c74ad251Schristos                                      "Wireless - IEEE 802.20",
350c74ad251Schristos                                      "Wireless - IEEE 802.22",
351c74ad251Schristos                                      /* ^ [20, 29] ^ */
352c74ad251Schristos                                      "PPPoA",
353c74ad251Schristos                                      "PPPoEoA",
354c74ad251Schristos                                      "PPPoEoE",
355c74ad251Schristos                                      "PPPoEoVLAN",
356c74ad251Schristos                                      "PPPoEoQinQ",
357c74ad251Schristos                                      "xPON",
358c74ad251Schristos                                      "Wireless - XGP",
359c74ad251Schristos                                      "WiMAX Pre-Release 8 IWK Function",
360c74ad251Schristos                                      "WIMAX-WIFI-IWK",
361c74ad251Schristos                                      "WIMAX-SFF",
362c74ad251Schristos                                      /* ^ [30, 39] ^ */
363c74ad251Schristos                                      "WIMAX-HA-LMA",
364c74ad251Schristos                                      "WIMAX-DHCP",
365c74ad251Schristos                                      "WIMAX-LBS",
366c74ad251Schristos                                      "WIMAX-WVS",
3670f74e101Schristos                                    };
3680f74e101Schristos 
3690f74e101Schristos /* Acct-Status-Type Accounting Attribute standard values */
370c74ad251Schristos /* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-10 */
3710f74e101Schristos static const char *acct_status[]={ NULL,
3720f74e101Schristos                                    "Start",
3730f74e101Schristos                                    "Stop",
3740f74e101Schristos                                    "Interim-Update",
3750f74e101Schristos                                    "Unassigned",
3760f74e101Schristos                                    "Unassigned",
3770f74e101Schristos                                    "Unassigned",
3780f74e101Schristos                                    "Accounting-On",
3790f74e101Schristos                                    "Accounting-Off",
3800f74e101Schristos                                    "Tunnel-Start",
381c74ad251Schristos                                      /* ^ [0, 9] ^ */
3820f74e101Schristos                                    "Tunnel-Stop",
3830f74e101Schristos                                    "Tunnel-Reject",
3840f74e101Schristos                                    "Tunnel-Link-Start",
3850f74e101Schristos                                    "Tunnel-Link-Stop",
3860f74e101Schristos                                    "Tunnel-Link-Reject",
3870f74e101Schristos                                    "Failed",
3880f74e101Schristos                                  };
3890f74e101Schristos 
3900f74e101Schristos /* Acct-Authentic Accounting Attribute standard values */
391c74ad251Schristos /* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-11 */
3920f74e101Schristos static const char *acct_auth[]={ NULL,
3930f74e101Schristos                                  "RADIUS",
3940f74e101Schristos                                  "Local",
3950f74e101Schristos                                  "Remote",
396c74ad251Schristos                                  "Diameter",
3970f74e101Schristos                                };
3980f74e101Schristos 
3990f74e101Schristos /* Acct-Terminate-Cause Accounting Attribute standard values */
400c74ad251Schristos /* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-12 */
4010f74e101Schristos static const char *acct_term[]={ NULL,
4020f74e101Schristos                                  "User Request",
4030f74e101Schristos                                  "Lost Carrier",
4040f74e101Schristos                                  "Lost Service",
4050f74e101Schristos                                  "Idle Timeout",
4060f74e101Schristos                                  "Session Timeout",
4070f74e101Schristos                                  "Admin Reset",
4080f74e101Schristos                                  "Admin Reboot",
4090f74e101Schristos                                  "Port Error",
4100f74e101Schristos                                  "NAS Error",
411c74ad251Schristos                                  /* ^ [0, 9] ^ */
4120f74e101Schristos                                  "NAS Request",
4130f74e101Schristos                                  "NAS Reboot",
4140f74e101Schristos                                  "Port Unneeded",
4150f74e101Schristos                                  "Port Preempted",
4160f74e101Schristos                                  "Port Suspended",
4170f74e101Schristos                                  "Service Unavailable",
4180f74e101Schristos                                  "Callback",
4190f74e101Schristos                                  "User Error",
4200f74e101Schristos                                  "Host Request",
421c74ad251Schristos                                  "Supplicant Restart",
422c74ad251Schristos                                  /* ^ [10, 19] ^ */
423c74ad251Schristos                                  "Reauthentication Failure",
424c74ad251Schristos                                  "Port Reinitialized",
425c74ad251Schristos                                  "Port Administratively Disabled",
426c74ad251Schristos                                  "Lost Power",
4270f74e101Schristos                                };
4280f74e101Schristos 
4290f74e101Schristos /* Tunnel-Type Attribute standard values */
430c74ad251Schristos /* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-14 */
4310f74e101Schristos static const char *tunnel_type[]={ NULL,
4320f74e101Schristos                                    "PPTP",
4330f74e101Schristos                                    "L2F",
4340f74e101Schristos                                    "L2TP",
4350f74e101Schristos                                    "ATMP",
4360f74e101Schristos                                    "VTP",
4370f74e101Schristos                                    "AH",
4380f74e101Schristos                                    "IP-IP",
4390f74e101Schristos                                    "MIN-IP-IP",
4400f74e101Schristos                                    "ESP",
441c74ad251Schristos                                    /* ^ [0, 9] ^ */
4420f74e101Schristos                                    "GRE",
4430f74e101Schristos                                    "DVS",
4440f74e101Schristos                                    "IP-in-IP Tunneling",
445fdccd7e4Schristos                                    "VLAN",
4460f74e101Schristos                                  };
4470f74e101Schristos 
4480f74e101Schristos /* Tunnel-Medium-Type Attribute standard values */
449c74ad251Schristos /* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-15 */
4500f74e101Schristos static const char *tunnel_medium[]={ NULL,
4510f74e101Schristos                                      "IPv4",
4520f74e101Schristos                                      "IPv6",
4530f74e101Schristos                                      "NSAP",
4540f74e101Schristos                                      "HDLC",
4550f74e101Schristos                                      "BBN 1822",
4560f74e101Schristos                                      "802",
4570f74e101Schristos                                      "E.163",
4580f74e101Schristos                                      "E.164",
4590f74e101Schristos                                      "F.69",
460c74ad251Schristos                                      /* ^ [0, 9] ^ */
4610f74e101Schristos                                      "X.121",
4620f74e101Schristos                                      "IPX",
4630f74e101Schristos                                      "Appletalk",
4640f74e101Schristos                                      "Decnet IV",
4650f74e101Schristos                                      "Banyan Vines",
4660f74e101Schristos                                      "E.164 with NSAP subaddress",
4670f74e101Schristos                                    };
4680f74e101Schristos 
4690f74e101Schristos /* ARAP-Zone-Access Attribute standard values */
470c74ad251Schristos /* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-16 */
4710f74e101Schristos static const char *arap_zone[]={ NULL,
4720f74e101Schristos                                  "Only access to dfl zone",
4730f74e101Schristos                                  "Use zone filter inc.",
4740f74e101Schristos                                  "Not used",
4750f74e101Schristos                                  "Use zone filter exc.",
4760f74e101Schristos                                };
4770f74e101Schristos 
478c74ad251Schristos /* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-17 */
4790f74e101Schristos static const char *prompt[]={ "No Echo",
4800f74e101Schristos                               "Echo",
4810f74e101Schristos                             };
4820f74e101Schristos 
483c74ad251Schristos /* Error-Cause standard values */
484c74ad251Schristos /* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-18 */
485c74ad251Schristos #define ERROR_CAUSE_RESIDUAL_CONTEXT_REMOVED 201
486c74ad251Schristos #define ERROR_CAUSE_INVALID_EAP_PACKET 202
487c74ad251Schristos #define ERROR_CAUSE_UNSUPPORTED_ATTRIBUTE 401
488c74ad251Schristos #define ERROR_CAUSE_MISSING_ATTRIBUTE 402
489c74ad251Schristos #define ERROR_CAUSE_NAS_IDENTIFICATION_MISMATCH 403
490c74ad251Schristos #define ERROR_CAUSE_INVALID_REQUEST 404
491c74ad251Schristos #define ERROR_CAUSE_UNSUPPORTED_SERVICE 405
492c74ad251Schristos #define ERROR_CAUSE_UNSUPPORTED_EXTENSION 406
493c74ad251Schristos #define ERROR_CAUSE_INVALID_ATTRIBUTE_VALUE 407
494c74ad251Schristos #define ERROR_CAUSE_ADMINISTRATIVELY_PROHIBITED 501
495c74ad251Schristos #define ERROR_CAUSE_PROXY_REQUEST_NOT_ROUTABLE 502
496c74ad251Schristos #define ERROR_CAUSE_SESSION_CONTEXT_NOT_FOUND 503
497c74ad251Schristos #define ERROR_CAUSE_SESSION_CONTEXT_NOT_REMOVABLE 504
498c74ad251Schristos #define ERROR_CAUSE_PROXY_PROCESSING_ERROR 505
499c74ad251Schristos #define ERROR_CAUSE_RESOURCES_UNAVAILABLE 506
500c74ad251Schristos #define ERROR_CAUSE_REQUEST_INITIATED 507
501c74ad251Schristos #define ERROR_CAUSE_MULTIPLE_SESSION_SELECTION_UNSUPPORTED 508
502c74ad251Schristos #define ERROR_CAUSE_LOCATION_INFO_REQUIRED 509
503c74ad251Schristos static const struct tok errorcausetype[] = {
504c74ad251Schristos                                  { ERROR_CAUSE_RESIDUAL_CONTEXT_REMOVED,               "Residual Session Context Removed" },
505c74ad251Schristos                                  { ERROR_CAUSE_INVALID_EAP_PACKET,                     "Invalid EAP Packet (Ignored)" },
506c74ad251Schristos                                  { ERROR_CAUSE_UNSUPPORTED_ATTRIBUTE,                  "Unsupported Attribute" },
507c74ad251Schristos                                  { ERROR_CAUSE_MISSING_ATTRIBUTE,                      "Missing Attribute" },
508c74ad251Schristos                                  { ERROR_CAUSE_NAS_IDENTIFICATION_MISMATCH,            "NAS Identification Mismatch" },
509c74ad251Schristos                                  { ERROR_CAUSE_INVALID_REQUEST,                        "Invalid Request" },
510c74ad251Schristos                                  { ERROR_CAUSE_UNSUPPORTED_SERVICE,                    "Unsupported Service" },
511c74ad251Schristos                                  { ERROR_CAUSE_UNSUPPORTED_EXTENSION,                  "Unsupported Extension" },
512c74ad251Schristos                                  { ERROR_CAUSE_INVALID_ATTRIBUTE_VALUE,                "Invalid Attribute Value" },
513c74ad251Schristos                                  { ERROR_CAUSE_ADMINISTRATIVELY_PROHIBITED,            "Administratively Prohibited" },
514c74ad251Schristos                                  { ERROR_CAUSE_PROXY_REQUEST_NOT_ROUTABLE,             "Request Not Routable (Proxy)" },
515c74ad251Schristos                                  { ERROR_CAUSE_SESSION_CONTEXT_NOT_FOUND,              "Session Context Not Found" },
516c74ad251Schristos                                  { ERROR_CAUSE_SESSION_CONTEXT_NOT_REMOVABLE,          "Session Context Not Removable" },
517c74ad251Schristos                                  { ERROR_CAUSE_PROXY_PROCESSING_ERROR,                 "Other Proxy Processing Error" },
518c74ad251Schristos                                  { ERROR_CAUSE_RESOURCES_UNAVAILABLE,                  "Resources Unavailable" },
519c74ad251Schristos                                  { ERROR_CAUSE_REQUEST_INITIATED,                      "Request Initiated" },
520c74ad251Schristos                                  { ERROR_CAUSE_MULTIPLE_SESSION_SELECTION_UNSUPPORTED, "Multiple Session Selection Unsupported" },
521c74ad251Schristos                                  { ERROR_CAUSE_LOCATION_INFO_REQUIRED,                 "Location Info Required" },
522c74ad251Schristos 																 { 0, NULL }
523c74ad251Schristos                                };
5240f74e101Schristos 
525c74ad251Schristos /* MIP6-Feature-Vector standard values */
526c74ad251Schristos /* https://www.iana.org/assignments/aaa-parameters/aaa-parameters.xhtml */
527c74ad251Schristos #define MIP6_INTEGRATED 0x0000000000000001
528c74ad251Schristos #define LOCAL_HOME_AGENT_ASSIGNMENT 0x0000000000000002
529c74ad251Schristos #define PMIP6_SUPPORTED 0x0000010000000000
530c74ad251Schristos #define IP4_HOA_SUPPORTED 0x0000020000000000
531c74ad251Schristos #define LOCAL_MAG_ROUTING_SUPPORTED 0x0000040000000000
532c74ad251Schristos #define ASSIGN_LOCAL_IP 0x0000080000000000
533c74ad251Schristos #define MIP4_SUPPORTED 0x0000100000000000
534c74ad251Schristos #define OPTIMIZED_IDLE_MODE_MOBILITY 0x0000200000000000
535c74ad251Schristos #define GTPv2_SUPPORTED 0x0000400000000000
536c74ad251Schristos #define IP4_TRANSPORT_SUPPORTED 0x0000800000000000
537c74ad251Schristos #define IP4_HOA_ONLY_SUPPORTED 0x0001000000000000
538c74ad251Schristos #define INTER_MAG_ROUTING_SUPPORTED 0x0002000000000000
539c74ad251Schristos static const struct mip6_feature_vector {
540c74ad251Schristos                   uint64_t v;
541c74ad251Schristos                   const char *s;
542c74ad251Schristos                 } mip6_feature_vector[] = {
543c74ad251Schristos                                  { MIP6_INTEGRATED,             "MIP6_INTEGRATED" },
544c74ad251Schristos                                  { LOCAL_HOME_AGENT_ASSIGNMENT, "LOCAL_HOME_AGENT_ASSIGNMENT" },
545c74ad251Schristos                                  { PMIP6_SUPPORTED,             "PMIP6_SUPPORTED" },
546c74ad251Schristos                                  { IP4_HOA_SUPPORTED,           "IP4_HOA_SUPPORTED" },
547c74ad251Schristos                                  { LOCAL_MAG_ROUTING_SUPPORTED, "LOCAL_MAG_ROUTING_SUPPORTED" },
548c74ad251Schristos                                  { ASSIGN_LOCAL_IP,             "ASSIGN_LOCAL_IP" },
549c74ad251Schristos                                  { MIP4_SUPPORTED,              "MIP4_SUPPORTED" },
550c74ad251Schristos                                  { OPTIMIZED_IDLE_MODE_MOBILITY, "OPTIMIZED_IDLE_MODE_MOBILITY" },
551c74ad251Schristos                                  { GTPv2_SUPPORTED,             "GTPv2_SUPPORTED" },
552c74ad251Schristos                                  { IP4_TRANSPORT_SUPPORTED,     "IP4_TRANSPORT_SUPPORTED" },
553c74ad251Schristos                                  { IP4_HOA_ONLY_SUPPORTED,      "IP4_HOA_ONLY_SUPPORTED" },
554c74ad251Schristos                                  { INTER_MAG_ROUTING_SUPPORTED, "INTER_MAG_ROUTING_SUPPORTED" },
555c74ad251Schristos                                };
556c74ad251Schristos 
557c74ad251Schristos /* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-19 */
558c74ad251Schristos #define OPERATOR_NAME_TADIG 0x30
559c74ad251Schristos #define OPERATOR_NAME_REALM 0x31
560c74ad251Schristos #define OPERATOR_NAME_E212  0x32
561c74ad251Schristos #define OPERATOR_NAME_ICC   0x33
562c74ad251Schristos static const struct tok operator_name_vector[] = {
563c74ad251Schristos                                  { OPERATOR_NAME_TADIG, "TADIG" },
564c74ad251Schristos                                  { OPERATOR_NAME_REALM, "REALM" },
565c74ad251Schristos                                  { OPERATOR_NAME_E212,  "E212"  },
566c74ad251Schristos                                  { OPERATOR_NAME_ICC,   "ICC"   },
567c74ad251Schristos                                  { 0, NULL }
568c74ad251Schristos                                };
569c74ad251Schristos 
570c74ad251Schristos /* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-20 */
571c74ad251Schristos #define LOCATION_INFORMATION_CODE_CIVIC      0
572c74ad251Schristos #define LOCATION_INFORMATION_CODE_GEOSPATIAL 1
573c74ad251Schristos static const struct tok location_information_code_vector[] = {
574c74ad251Schristos                                  { LOCATION_INFORMATION_CODE_CIVIC     , "Civic"      },
575c74ad251Schristos                                  { LOCATION_INFORMATION_CODE_GEOSPATIAL, "Geospatial" },
576c74ad251Schristos                                  { 0, NULL }
577c74ad251Schristos                                };
578c74ad251Schristos 
579c74ad251Schristos /* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-21 */
580c74ad251Schristos #define LOCATION_INFORMATION_ENTITY_USER   0
581c74ad251Schristos #define LOCATION_INFORMATION_ENTITY_RADIUS 1
582c74ad251Schristos static const struct tok location_information_entity_vector[] = {
583c74ad251Schristos                                  { LOCATION_INFORMATION_ENTITY_USER,   "User"   },
584c74ad251Schristos                                  { LOCATION_INFORMATION_ENTITY_RADIUS, "RADIUS" },
585c74ad251Schristos                                  { 0, NULL }
586c74ad251Schristos                                };
587c74ad251Schristos 
588c74ad251Schristos /* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-22 */
589c74ad251Schristos static const struct tok blpr_bm[] = {
590c74ad251Schristos                                  { 0x0001, "MBZ-15" },
591c74ad251Schristos                                  { 0x0002, "MBZ-14" },
592c74ad251Schristos                                  { 0x0004, "MBZ-13" },
593c74ad251Schristos                                  { 0x0008, "MBZ-12" },
594c74ad251Schristos                                  { 0x0010, "MBZ-11" },
595c74ad251Schristos                                  { 0x0020, "MBZ-10" },
596c74ad251Schristos                                  { 0x0040, "MBZ-9" },
597c74ad251Schristos                                  { 0x0080, "MBZ-8" },
598c74ad251Schristos                                  { 0x0100, "MBZ-7" },
599c74ad251Schristos                                  { 0x0200, "MBZ-6" },
600c74ad251Schristos                                  { 0x0400, "MBZ-5" },
601c74ad251Schristos                                  { 0x0800, "MBZ-4" },
602c74ad251Schristos                                  { 0x1000, "MBZ-3" },
603c74ad251Schristos                                  { 0x2000, "MBZ-2" },
604c74ad251Schristos                                  { 0x4000, "MBZ-1" },
605c74ad251Schristos                                  { 0x8000, "Retransmission Allowed" },
606c74ad251Schristos                                  { 0, NULL }
607c74ad251Schristos                                };
608c74ad251Schristos 
609c74ad251Schristos /* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-2 */
610c74ad251Schristos static const struct attrtype {
611dc860a36Sspz                   const char *name;      /* Attribute name                 */
6120f74e101Schristos                   const char **subtypes; /* Standard Values (if any)       */
6130f74e101Schristos                   u_char siz_subtypes;   /* Size of total standard values  */
6140f74e101Schristos                   u_char first_subtype;  /* First standard value is 0 or 1 */
615c74ad251Schristos                   void (*print_func)(netdissect_options *, const u_char *, u_int, u_short);
6160f74e101Schristos                 } attr_type[]=
6170f74e101Schristos   {
6180f74e101Schristos      { NULL,                              NULL, 0, 0, NULL               },
619ba2ff121Schristos      { "User-Name",                       NULL, 0, 0, print_attr_string  },
620ba2ff121Schristos      { "User-Password",                   NULL, 0, 0, NULL               },
621ba2ff121Schristos      { "CHAP-Password",                   NULL, 0, 0, NULL               },
622ba2ff121Schristos      { "NAS-IP-Address",                  NULL, 0, 0, print_attr_address },
623ba2ff121Schristos      { "NAS-Port",                        NULL, 0, 0, print_attr_num     },
624ba2ff121Schristos      { "Service-Type",                    serv_type, TAM_SIZE(serv_type)-1, 1, print_attr_num },
625ba2ff121Schristos      { "Framed-Protocol",                 frm_proto, TAM_SIZE(frm_proto)-1, 1, print_attr_num },
626ba2ff121Schristos      { "Framed-IP-Address",               NULL, 0, 0, print_attr_address },
627ba2ff121Schristos      { "Framed-IP-Netmask",               NULL, 0, 0, print_attr_address },
628c74ad251Schristos      /* ^ [0, 9] ^ */
629ba2ff121Schristos      { "Framed-Routing",                  frm_routing, TAM_SIZE(frm_routing), 0, print_attr_num },
630ba2ff121Schristos      { "Filter-Id",                       NULL, 0, 0, print_attr_string  },
631ba2ff121Schristos      { "Framed-MTU",                      NULL, 0, 0, print_attr_num     },
632ba2ff121Schristos      { "Framed-Compression",              frm_comp, TAM_SIZE(frm_comp),   0, print_attr_num },
633ba2ff121Schristos      { "Login-IP-Host",                   NULL, 0, 0, print_attr_address },
634ba2ff121Schristos      { "Login-Service",                   login_serv, TAM_SIZE(login_serv), 0, print_attr_num },
635ba2ff121Schristos      { "Login-TCP-Port",                  NULL, 0, 0, print_attr_num     },
6360f74e101Schristos      { "Unassigned",                      NULL, 0, 0, NULL }, /*17*/
637ba2ff121Schristos      { "Reply-Message",                   NULL, 0, 0, print_attr_string },
638ba2ff121Schristos      { "Callback-Number",                 NULL, 0, 0, print_attr_string },
639c74ad251Schristos      /* ^ [10, 19] ^ */
640ba2ff121Schristos      { "Callback-Id",                     NULL, 0, 0, print_attr_string },
6410f74e101Schristos      { "Unassigned",                      NULL, 0, 0, NULL }, /*21*/
642ba2ff121Schristos      { "Framed-Route",                    NULL, 0, 0, print_attr_string },
643ba2ff121Schristos      { "Framed-IPX-Network",              NULL, 0, 0, print_attr_num    },
6440f74e101Schristos      { "State",                           NULL, 0, 0, print_attr_string },
6450f74e101Schristos      { "Class",                           NULL, 0, 0, print_attr_string },
646ba2ff121Schristos      { "Vendor-Specific",                 NULL, 0, 0, print_vendor_attr },
647ba2ff121Schristos      { "Session-Timeout",                 NULL, 0, 0, print_attr_num    },
648ba2ff121Schristos      { "Idle-Timeout",                    NULL, 0, 0, print_attr_num    },
649ba2ff121Schristos      { "Termination-Action",              term_action, TAM_SIZE(term_action), 0, print_attr_num },
650c74ad251Schristos      /* ^ [20, 29] ^ */
651ba2ff121Schristos      { "Called-Station-Id",               NULL, 0, 0, print_attr_string },
652ba2ff121Schristos      { "Calling-Station-Id",              NULL, 0, 0, print_attr_string },
653ba2ff121Schristos      { "NAS-Identifier",                  NULL, 0, 0, print_attr_string },
654ba2ff121Schristos      { "Proxy-State",                     NULL, 0, 0, print_attr_string },
655ba2ff121Schristos      { "Login-LAT-Service",               NULL, 0, 0, print_attr_string },
656ba2ff121Schristos      { "Login-LAT-Node",                  NULL, 0, 0, print_attr_string },
657ba2ff121Schristos      { "Login-LAT-Group",                 NULL, 0, 0, print_attr_string },
658ba2ff121Schristos      { "Framed-AppleTalk-Link",           NULL, 0, 0, print_attr_num    },
659ba2ff121Schristos      { "Framed-AppleTalk-Network",        NULL, 0, 0, print_attr_num    },
660ba2ff121Schristos      { "Framed-AppleTalk-Zone",           NULL, 0, 0, print_attr_string },
661c74ad251Schristos      /* ^ [30, 39] ^ */
662ba2ff121Schristos      { "Acct-Status-Type",                acct_status, TAM_SIZE(acct_status)-1, 1, print_attr_num },
663ba2ff121Schristos      { "Acct-Delay-Time",                 NULL, 0, 0, print_attr_num    },
664ba2ff121Schristos      { "Acct-Input-Octets",               NULL, 0, 0, print_attr_num    },
665ba2ff121Schristos      { "Acct-Output-Octets",              NULL, 0, 0, print_attr_num    },
666ba2ff121Schristos      { "Acct-Session-Id",                 NULL, 0, 0, print_attr_string },
667ba2ff121Schristos      { "Acct-Authentic",                  acct_auth, TAM_SIZE(acct_auth)-1, 1, print_attr_num },
668ba2ff121Schristos      { "Acct-Session-Time",               NULL, 0, 0, print_attr_num },
669ba2ff121Schristos      { "Acct-Input-Packets",              NULL, 0, 0, print_attr_num },
670ba2ff121Schristos      { "Acct-Output-Packets",             NULL, 0, 0, print_attr_num },
671ba2ff121Schristos      { "Acct-Terminate-Cause",            acct_term, TAM_SIZE(acct_term)-1, 1, print_attr_num },
672c74ad251Schristos      /* ^ [40, 49] ^ */
673ba2ff121Schristos      { "Acct-Multi-Session-Id",           NULL, 0, 0, print_attr_string },
674ba2ff121Schristos      { "Acct-Link-Count",                 NULL, 0, 0, print_attr_num },
675ba2ff121Schristos      { "Acct-Input-Gigawords",            NULL, 0, 0, print_attr_num },
676ba2ff121Schristos      { "Acct-Output-Gigawords",           NULL, 0, 0, print_attr_num },
6770f74e101Schristos      { "Unassigned",                      NULL, 0, 0, NULL }, /*54*/
678ba2ff121Schristos      { "Event-Timestamp",                 NULL, 0, 0, print_attr_time },
679ba2ff121Schristos      { "Egress-VLANID",                   NULL, 0, 0, print_attr_num },
680ba2ff121Schristos      { "Ingress-Filters",                 ingress_filters, TAM_SIZE(ingress_filters)-1, 1, print_attr_num },
681ba2ff121Schristos      { "Egress-VLAN-Name",                NULL, 0, 0, print_attr_string },
682ba2ff121Schristos      { "User-Priority-Table",             NULL, 0, 0, NULL },
683c74ad251Schristos      /* ^ [50, 59] ^ */
684ba2ff121Schristos      { "CHAP-Challenge",                  NULL, 0, 0, print_attr_string },
685ba2ff121Schristos      { "NAS-Port-Type",                   nas_port_type, TAM_SIZE(nas_port_type), 0, print_attr_num },
686ba2ff121Schristos      { "Port-Limit",                      NULL, 0, 0, print_attr_num },
687ba2ff121Schristos      { "Login-LAT-Port",                  NULL, 0, 0, print_attr_string }, /*63*/
688ba2ff121Schristos      { "Tunnel-Type",                     tunnel_type, TAM_SIZE(tunnel_type)-1, 1, print_attr_num },
689ba2ff121Schristos      { "Tunnel-Medium-Type",              tunnel_medium, TAM_SIZE(tunnel_medium)-1, 1, print_attr_num },
690ba2ff121Schristos      { "Tunnel-Client-Endpoint",          NULL, 0, 0, print_attr_string },
691ba2ff121Schristos      { "Tunnel-Server-Endpoint",          NULL, 0, 0, print_attr_string },
692ba2ff121Schristos      { "Acct-Tunnel-Connection",          NULL, 0, 0, print_attr_string },
693ba2ff121Schristos      { "Tunnel-Password",                 NULL, 0, 0, print_attr_string  },
694c74ad251Schristos      /* ^ [60, 69] ^ */
695ba2ff121Schristos      { "ARAP-Password",                   NULL, 0, 0, print_attr_strange },
696ba2ff121Schristos      { "ARAP-Features",                   NULL, 0, 0, print_attr_strange },
697ba2ff121Schristos      { "ARAP-Zone-Access",                arap_zone, TAM_SIZE(arap_zone)-1, 1, print_attr_num }, /*72*/
698ba2ff121Schristos      { "ARAP-Security",                   NULL, 0, 0, print_attr_string },
699ba2ff121Schristos      { "ARAP-Security-Data",              NULL, 0, 0, print_attr_string },
700ba2ff121Schristos      { "Password-Retry",                  NULL, 0, 0, print_attr_num    },
7010f74e101Schristos      { "Prompt",                          prompt, TAM_SIZE(prompt), 0, print_attr_num },
702ba2ff121Schristos      { "Connect-Info",                    NULL, 0, 0, print_attr_string   },
703ba2ff121Schristos      { "Configuration-Token",             NULL, 0, 0, print_attr_string   },
704ba2ff121Schristos      { "EAP-Message",                     NULL, 0, 0, print_attr_string   },
705c74ad251Schristos      /* ^ [70, 79] ^ */
706ba2ff121Schristos      { "Message-Authenticator",           NULL, 0, 0, print_attr_string }, /*80*/
707ba2ff121Schristos      { "Tunnel-Private-Group-ID",         NULL, 0, 0, print_attr_string },
708ba2ff121Schristos      { "Tunnel-Assignment-ID",            NULL, 0, 0, print_attr_string },
709ba2ff121Schristos      { "Tunnel-Preference",               NULL, 0, 0, print_attr_num    },
710ba2ff121Schristos      { "ARAP-Challenge-Response",         NULL, 0, 0, print_attr_strange },
711ba2ff121Schristos      { "Acct-Interim-Interval",           NULL, 0, 0, print_attr_num     },
712ba2ff121Schristos      { "Acct-Tunnel-Packets-Lost",        NULL, 0, 0, print_attr_num }, /*86*/
713ba2ff121Schristos      { "NAS-Port-Id",                     NULL, 0, 0, print_attr_string },
714ba2ff121Schristos      { "Framed-Pool",                     NULL, 0, 0, print_attr_string },
715ba2ff121Schristos      { "CUI",                             NULL, 0, 0, print_attr_string },
716c74ad251Schristos      /* ^ [80, 89] ^ */
717ba2ff121Schristos      { "Tunnel-Client-Auth-ID",           NULL, 0, 0, print_attr_string },
718ba2ff121Schristos      { "Tunnel-Server-Auth-ID",           NULL, 0, 0, print_attr_string },
719c74ad251Schristos      { "NAS-Filter-Rule",                 NULL, 0, 0, print_attr_string },
720c74ad251Schristos      { "Unassigned",                      NULL, 0, 0, NULL },  /*93*/
721c74ad251Schristos      { "Originating-Line-Info",           NULL, 0, 0, NULL },
722c74ad251Schristos      { "NAS-IPv6-Address",                NULL, 0, 0, print_attr_address6 },
723c74ad251Schristos      { "Framed-Interface-ID",             NULL, 0, 0, NULL },
724c74ad251Schristos      { "Framed-IPv6-Prefix",              NULL, 0, 0, print_attr_netmask6 },
725c74ad251Schristos      { "Login-IPv6-Host",                 NULL, 0, 0, print_attr_address6 },
726c74ad251Schristos      { "Framed-IPv6-Route",               NULL, 0, 0, print_attr_string },
727c74ad251Schristos      /* ^ [90, 99] ^ */
728c74ad251Schristos      { "Framed-IPv6-Pool",                NULL, 0, 0, print_attr_string },
729c74ad251Schristos      { "Error-Cause",                     NULL, 0, 0, print_attr_strange },
730c74ad251Schristos      { "EAP-Key-Name",                    NULL, 0, 0, NULL },
731c74ad251Schristos      { "Digest-Response",                 NULL, 0, 0, print_attr_string },
732c74ad251Schristos      { "Digest-Realm",                    NULL, 0, 0, print_attr_string },
733c74ad251Schristos      { "Digest-Nonce",                    NULL, 0, 0, print_attr_string },
734c74ad251Schristos      { "Digest-Response-Auth",            NULL, 0, 0, print_attr_string },
735c74ad251Schristos      { "Digest-Nextnonce",                NULL, 0, 0, print_attr_string },
736c74ad251Schristos      { "Digest-Method",                   NULL, 0, 0, print_attr_string },
737c74ad251Schristos      { "Digest-URI",                      NULL, 0, 0, print_attr_string },
738c74ad251Schristos      /* ^ [100, 109] ^ */
739c74ad251Schristos      { "Digest-Qop",                      NULL, 0, 0, print_attr_string },
740c74ad251Schristos      { "Digest-Algorithm",                NULL, 0, 0, print_attr_string },
741c74ad251Schristos      { "Digest-Entity-Body-Hash",         NULL, 0, 0, print_attr_string },
742c74ad251Schristos      { "Digest-CNonce",                   NULL, 0, 0, print_attr_string },
743c74ad251Schristos      { "Digest-Nonce-Count",              NULL, 0, 0, print_attr_string },
744c74ad251Schristos      { "Digest-Username",                 NULL, 0, 0, print_attr_string },
745c74ad251Schristos      { "Digest-Opaque",                   NULL, 0, 0, print_attr_string },
746c74ad251Schristos      { "Digest-Auth-Param",               NULL, 0, 0, print_attr_string },
747c74ad251Schristos      { "Digest-AKA-Auts",                 NULL, 0, 0, print_attr_string },
748c74ad251Schristos      { "Digest-Domain",                   NULL, 0, 0, print_attr_string },
749c74ad251Schristos      /* ^ [110, 119] ^ */
750c74ad251Schristos      { "Digest-Stale",                    NULL, 0, 0, print_attr_string },
751c74ad251Schristos      { "Digest-HA1",                      NULL, 0, 0, print_attr_string },
752c74ad251Schristos      { "SIP-AOR",                         NULL, 0, 0, print_attr_string },
753c74ad251Schristos      { "Delegated-IPv6-Prefix",           NULL, 0, 0, print_attr_netmask6 },
754c74ad251Schristos      { "MIP6-Feature-Vector",             NULL, 0, 0, print_attr_vector64 },
755c74ad251Schristos      { "MIP6-Home-Link-Prefix",           NULL, 0, 0, print_attr_mip6_home_link_prefix },
756c74ad251Schristos      { "Operator-Name",                   NULL, 0, 0, print_attr_operator_name },
757c74ad251Schristos      { "Location-Information",            NULL, 0, 0, print_attr_location_information },
758c74ad251Schristos      { "Location-Data",                   NULL, 0, 0, print_attr_location_data },
759c74ad251Schristos      { "Basic-Location-Policy-Rules",     NULL, 0, 0, print_basic_location_policy_rules }
760c74ad251Schristos      /* ^ [120, 129] ^ */
7610f74e101Schristos   };
7620f74e101Schristos 
7630f74e101Schristos 
7640f74e101Schristos /*****************************/
7650f74e101Schristos /* Print an attribute string */
7660f74e101Schristos /* value pointed by 'data'   */
7670f74e101Schristos /* and 'length' size.        */
7680f74e101Schristos /*****************************/
7690f74e101Schristos /* Returns nothing.          */
7700f74e101Schristos /*****************************/
7710f74e101Schristos static void
772b3a00663Schristos print_attr_string(netdissect_options *ndo,
773c74ad251Schristos                   const u_char *data, u_int length, u_short attr_code)
7740f74e101Schristos {
775c74ad251Schristos    u_int i;
7760f74e101Schristos 
777c74ad251Schristos    ND_TCHECK_LEN(data, length);
7780f74e101Schristos 
779*26ba0b50Schristos    switch(attr_code) {
7800f74e101Schristos       case TUNNEL_PASS:
7810f74e101Schristos            if (length < 3)
78272c96ff3Schristos               goto trunc;
783c74ad251Schristos            if (GET_U_1(data) && (GET_U_1(data) <= 0x1F))
784c74ad251Schristos               ND_PRINT("Tag[%u] ", GET_U_1(data));
785ba2ff121Schristos            else
786c74ad251Schristos               ND_PRINT("Tag[Unused] ");
7870f74e101Schristos            data++;
7880f74e101Schristos            length--;
789c74ad251Schristos            ND_PRINT("Salt %u ", GET_BE_U_2(data));
7900f74e101Schristos            data+=2;
7910f74e101Schristos            length-=2;
7920f74e101Schristos         break;
7930f74e101Schristos       case TUNNEL_CLIENT_END:
7940f74e101Schristos       case TUNNEL_SERVER_END:
7950f74e101Schristos       case TUNNEL_PRIV_GROUP:
7960f74e101Schristos       case TUNNEL_ASSIGN_ID:
7970f74e101Schristos       case TUNNEL_CLIENT_AUTH:
7980f74e101Schristos       case TUNNEL_SERVER_AUTH:
799*26ba0b50Schristos            if (GET_U_1(data) <= 0x1F) {
8000f74e101Schristos               if (length < 1)
80172c96ff3Schristos                  goto trunc;
802c74ad251Schristos               if (GET_U_1(data))
803c74ad251Schristos                 ND_PRINT("Tag[%u] ", GET_U_1(data));
804ba2ff121Schristos               else
805c74ad251Schristos                 ND_PRINT("Tag[Unused] ");
8060f74e101Schristos               data++;
8070f74e101Schristos               length--;
8080f74e101Schristos            }
8090f74e101Schristos         break;
810ba2ff121Schristos       case EGRESS_VLAN_NAME:
81172c96ff3Schristos            if (length < 1)
81272c96ff3Schristos               goto trunc;
813c74ad251Schristos            ND_PRINT("%s (0x%02x) ",
814c74ad251Schristos                   tok2str(rfc4675_tagged,"Unknown tag",GET_U_1(data)),
815c74ad251Schristos                   GET_U_1(data));
816ba2ff121Schristos            data++;
817ba2ff121Schristos            length--;
818ba2ff121Schristos         break;
819c74ad251Schristos       case EAP_MESSAGE:
820c74ad251Schristos            if (length < 1)
821c74ad251Schristos               goto trunc;
822c74ad251Schristos            eap_print(ndo, data, length);
823c74ad251Schristos            return;
8240f74e101Schristos    }
8250f74e101Schristos 
826c74ad251Schristos    for (i=0; i < length && GET_U_1(data); i++, data++)
827c74ad251Schristos        ND_PRINT("%c", ND_ASCII_ISPRINT(GET_U_1(data)) ? GET_U_1(data) : '.');
8280f74e101Schristos 
8290f74e101Schristos    return;
8300f74e101Schristos 
8310f74e101Schristos    trunc:
832c74ad251Schristos       nd_print_trunc(ndo);
8330f74e101Schristos }
8340f74e101Schristos 
8350f74e101Schristos /*
8360f74e101Schristos  * print vendor specific attributes
8370f74e101Schristos  */
8380f74e101Schristos static void
839b3a00663Schristos print_vendor_attr(netdissect_options *ndo,
840c74ad251Schristos                   const u_char *data, u_int length, u_short attr_code _U_)
8410f74e101Schristos {
8420f74e101Schristos     u_int idx;
8430f74e101Schristos     u_int vendor_id;
8440f74e101Schristos     u_int vendor_type;
8450f74e101Schristos     u_int vendor_length;
8460f74e101Schristos 
8470f74e101Schristos     if (length < 4)
8480f74e101Schristos         goto trunc;
849c74ad251Schristos     vendor_id = GET_BE_U_4(data);
8500f74e101Schristos     data+=4;
8510f74e101Schristos     length-=4;
8520f74e101Schristos 
853c74ad251Schristos     ND_PRINT("Vendor: %s (%u)",
8540f74e101Schristos            tok2str(smi_values,"Unknown",vendor_id),
855c74ad251Schristos            vendor_id);
8560f74e101Schristos 
8570f74e101Schristos     while (length >= 2) {
858c74ad251Schristos         vendor_type = GET_U_1(data);
859c74ad251Schristos         vendor_length = GET_U_1(data + 1);
8600f74e101Schristos 
861*26ba0b50Schristos         if (vendor_length < 2) {
862c74ad251Schristos             ND_PRINT("\n\t    Vendor Attribute: %u, Length: %u (bogus, must be >= 2)",
8630f74e101Schristos                    vendor_type,
864c74ad251Schristos                    vendor_length);
8650f74e101Schristos             return;
8660f74e101Schristos         }
867*26ba0b50Schristos         if (vendor_length > length) {
868c74ad251Schristos             ND_PRINT("\n\t    Vendor Attribute: %u, Length: %u (bogus, goes past end of vendor-specific attribute)",
8690f74e101Schristos                    vendor_type,
870c74ad251Schristos                    vendor_length);
8710f74e101Schristos             return;
8720f74e101Schristos         }
8730f74e101Schristos         data+=2;
8740f74e101Schristos         vendor_length-=2;
8750f74e101Schristos         length-=2;
876c74ad251Schristos 	ND_TCHECK_LEN(data, vendor_length);
8770f74e101Schristos 
878c74ad251Schristos         ND_PRINT("\n\t    Vendor Attribute: %u, Length: %u, Value: ",
8790f74e101Schristos                vendor_type,
880c74ad251Schristos                vendor_length);
8810f74e101Schristos         for (idx = 0; idx < vendor_length ; idx++, data++)
882c74ad251Schristos             ND_PRINT("%c", ND_ASCII_ISPRINT(GET_U_1(data)) ? GET_U_1(data) : '.');
8830f74e101Schristos         length-=vendor_length;
8840f74e101Schristos     }
8850f74e101Schristos     return;
8860f74e101Schristos 
8870f74e101Schristos    trunc:
888c74ad251Schristos      nd_print_trunc(ndo);
8890f74e101Schristos }
8900f74e101Schristos 
8910f74e101Schristos /******************************/
8920f74e101Schristos /* Print an attribute numeric */
8930f74e101Schristos /* value pointed by 'data'    */
8940f74e101Schristos /* and 'length' size.         */
8950f74e101Schristos /******************************/
8960f74e101Schristos /* Returns nothing.           */
8970f74e101Schristos /******************************/
8980f74e101Schristos static void
899b3a00663Schristos print_attr_num(netdissect_options *ndo,
900c74ad251Schristos                const u_char *data, u_int length, u_short attr_code)
9010f74e101Schristos {
902b3a00663Schristos    uint32_t timeout;
9030f74e101Schristos 
904*26ba0b50Schristos    if (length != 4) {
905c74ad251Schristos        ND_PRINT("ERROR: length %u != 4", length);
9060f74e101Schristos        return;
9070f74e101Schristos    }
9080f74e101Schristos 
9090f74e101Schristos                           /* This attribute has standard values */
910*26ba0b50Schristos    if (attr_type[attr_code].siz_subtypes) {
9110f74e101Schristos       static const char **table;
912b3a00663Schristos       uint32_t data_value;
9130f74e101Schristos       table = attr_type[attr_code].subtypes;
9140f74e101Schristos 
915*26ba0b50Schristos       if ( (attr_code == TUNNEL_TYPE) || (attr_code == TUNNEL_MEDIUM) ) {
916c74ad251Schristos          if (!GET_U_1(data))
917c74ad251Schristos             ND_PRINT("Tag[Unused] ");
9180f74e101Schristos          else
919c74ad251Schristos             ND_PRINT("Tag[%u] ", GET_U_1(data));
9200f74e101Schristos          data++;
921c74ad251Schristos          data_value = GET_BE_U_3(data);
922*26ba0b50Schristos       } else {
923c74ad251Schristos          data_value = GET_BE_U_4(data);
9240f74e101Schristos       }
925b3a00663Schristos       if ( data_value <= (uint32_t)(attr_type[attr_code].siz_subtypes - 1 +
9260f74e101Schristos             attr_type[attr_code].first_subtype) &&
9270f74e101Schristos 	   data_value >= attr_type[attr_code].first_subtype )
928c74ad251Schristos          ND_PRINT("%s", table[data_value]);
9290f74e101Schristos       else
930c74ad251Schristos          ND_PRINT("#%u", data_value);
931*26ba0b50Schristos    } else {
9320f74e101Schristos       switch(attr_code) /* Be aware of special cases... */
9330f74e101Schristos       {
9340f74e101Schristos         case FRM_IPX:
935c74ad251Schristos              if (GET_BE_U_4(data) == 0xFFFFFFFE )
936c74ad251Schristos                 ND_PRINT("NAS Select");
9370f74e101Schristos              else
938c74ad251Schristos                 ND_PRINT("%u", GET_BE_U_4(data));
9390f74e101Schristos           break;
9400f74e101Schristos 
9410f74e101Schristos         case SESSION_TIMEOUT:
9420f74e101Schristos         case IDLE_TIMEOUT:
9430f74e101Schristos         case ACCT_DELAY:
9440f74e101Schristos         case ACCT_SESSION_TIME:
9450f74e101Schristos         case ACCT_INT_INTERVAL:
946c74ad251Schristos              timeout = GET_BE_U_4(data);
9470f74e101Schristos              if ( timeout < 60 )
948c74ad251Schristos                 ND_PRINT("%02d secs", timeout);
949*26ba0b50Schristos              else {
9500f74e101Schristos                 if ( timeout < 3600 )
951c74ad251Schristos                    ND_PRINT("%02d:%02d min",
952c74ad251Schristos                           timeout / 60, timeout % 60);
9530f74e101Schristos                 else
954c74ad251Schristos                    ND_PRINT("%02d:%02d:%02d hours",
9550f74e101Schristos                           timeout / 3600, (timeout % 3600) / 60,
956c74ad251Schristos                           timeout % 60);
9570f74e101Schristos              }
9580f74e101Schristos           break;
9590f74e101Schristos 
9600f74e101Schristos         case FRM_ATALK_LINK:
961c74ad251Schristos              if (GET_BE_U_4(data))
962c74ad251Schristos                 ND_PRINT("%u", GET_BE_U_4(data));
9630f74e101Schristos              else
964c74ad251Schristos                 ND_PRINT("Unnumbered");
9650f74e101Schristos           break;
9660f74e101Schristos 
9670f74e101Schristos         case FRM_ATALK_NETWORK:
968c74ad251Schristos              if (GET_BE_U_4(data))
969c74ad251Schristos                 ND_PRINT("%u", GET_BE_U_4(data));
9700f74e101Schristos              else
971c74ad251Schristos                 ND_PRINT("NAS assigned");
9720f74e101Schristos           break;
9730f74e101Schristos 
9740f74e101Schristos         case TUNNEL_PREFERENCE:
975c74ad251Schristos             if (GET_U_1(data))
976c74ad251Schristos                ND_PRINT("Tag[%u] ", GET_U_1(data));
9770f74e101Schristos             else
978c74ad251Schristos                ND_PRINT("Tag[Unused] ");
979ba2ff121Schristos             data++;
980c74ad251Schristos             ND_PRINT("%u", GET_BE_U_3(data));
981ba2ff121Schristos           break;
982ba2ff121Schristos 
983ba2ff121Schristos         case EGRESS_VLAN_ID:
984c74ad251Schristos             ND_PRINT("%s (0x%02x) ",
985c74ad251Schristos                    tok2str(rfc4675_tagged,"Unknown tag",GET_U_1(data)),
986c74ad251Schristos                    GET_U_1(data));
987ba2ff121Schristos             data++;
988c74ad251Schristos             ND_PRINT("%u", GET_BE_U_3(data));
9890f74e101Schristos           break;
9900f74e101Schristos 
9910f74e101Schristos         default:
992c74ad251Schristos              ND_PRINT("%u", GET_BE_U_4(data));
9930f74e101Schristos           break;
9940f74e101Schristos 
9950f74e101Schristos       } /* switch */
9960f74e101Schristos 
9970f74e101Schristos    } /* if-else */
9980f74e101Schristos }
9990f74e101Schristos 
10000f74e101Schristos /*****************************/
10010f74e101Schristos /* Print an attribute IPv4   */
10020f74e101Schristos /* address value pointed by  */
10030f74e101Schristos /* 'data' and 'length' size. */
10040f74e101Schristos /*****************************/
10050f74e101Schristos /* Returns nothing.          */
10060f74e101Schristos /*****************************/
10070f74e101Schristos static void
1008b3a00663Schristos print_attr_address(netdissect_options *ndo,
1009c74ad251Schristos                    const u_char *data, u_int length, u_short attr_code)
10100f74e101Schristos {
1011*26ba0b50Schristos    if (length != 4) {
1012c74ad251Schristos        ND_PRINT("ERROR: length %u != 4", length);
10130f74e101Schristos        return;
10140f74e101Schristos    }
10150f74e101Schristos 
1016*26ba0b50Schristos    switch(attr_code) {
10170f74e101Schristos       case FRM_IPADDR:
10180f74e101Schristos       case LOG_IPHOST:
1019c74ad251Schristos            if (GET_BE_U_4(data) == 0xFFFFFFFF )
1020c74ad251Schristos               ND_PRINT("User Selected");
10210f74e101Schristos            else
1022c74ad251Schristos               if (GET_BE_U_4(data) == 0xFFFFFFFE )
1023c74ad251Schristos                  ND_PRINT("NAS Select");
10240f74e101Schristos               else
1025c74ad251Schristos                  ND_PRINT("%s",GET_IPADDR_STRING(data));
10260f74e101Schristos       break;
10270f74e101Schristos 
10280f74e101Schristos       default:
1029c74ad251Schristos           ND_PRINT("%s", GET_IPADDR_STRING(data));
10300f74e101Schristos       break;
10310f74e101Schristos    }
1032c74ad251Schristos }
1033c74ad251Schristos 
1034c74ad251Schristos /*****************************/
1035c74ad251Schristos /* Print an attribute IPv6   */
1036c74ad251Schristos /* address value pointed by  */
1037c74ad251Schristos /* 'data' and 'length' size. */
1038c74ad251Schristos /*****************************/
1039c74ad251Schristos /* Returns nothing.          */
1040c74ad251Schristos /*****************************/
1041c74ad251Schristos static void
1042c74ad251Schristos print_attr_address6(netdissect_options *ndo,
1043c74ad251Schristos                    const u_char *data, u_int length, u_short attr_code _U_)
1044c74ad251Schristos {
1045*26ba0b50Schristos    if (length != 16) {
1046c74ad251Schristos        ND_PRINT("ERROR: length %u != 16", length);
1047c74ad251Schristos        return;
1048c74ad251Schristos    }
1049c74ad251Schristos 
1050c74ad251Schristos    ND_PRINT("%s", GET_IP6ADDR_STRING(data));
1051c74ad251Schristos }
1052c74ad251Schristos 
1053c74ad251Schristos static void
1054c74ad251Schristos print_attr_netmask6(netdissect_options *ndo,
1055c74ad251Schristos                     const u_char *data, u_int length, u_short attr_code _U_)
1056c74ad251Schristos {
1057c74ad251Schristos    u_char data2[16];
1058c74ad251Schristos 
1059*26ba0b50Schristos    if (length < 2 || length > 18) {
1060c74ad251Schristos        ND_PRINT("ERROR: length %u not in range (2..18)", length);
1061c74ad251Schristos        return;
1062c74ad251Schristos    }
1063c74ad251Schristos    ND_TCHECK_LEN(data, length);
1064*26ba0b50Schristos    if (GET_U_1(data + 1) > 128) {
1065c74ad251Schristos       ND_PRINT("ERROR: netmask %u not in range (0..128)", GET_U_1(data + 1));
1066c74ad251Schristos       return;
1067c74ad251Schristos    }
1068c74ad251Schristos 
1069c74ad251Schristos    memset(data2, 0, sizeof(data2));
1070c74ad251Schristos    if (length > 2)
1071c74ad251Schristos       memcpy(data2, data+2, length-2);
1072c74ad251Schristos 
1073c74ad251Schristos    ND_PRINT("%s/%u", ip6addr_string(ndo, data2), GET_U_1(data + 1)); /* local buffer, not packet data; don't use GET_IP6ADDR_STRING() */
1074c74ad251Schristos 
1075c74ad251Schristos    if (GET_U_1(data + 1) > 8 * (length - 2))
1076c74ad251Schristos       ND_PRINT(" (inconsistent prefix length)");
1077c74ad251Schristos 
1078c74ad251Schristos    return;
1079c74ad251Schristos 
1080c74ad251Schristos    trunc:
1081c74ad251Schristos      nd_print_trunc(ndo);
1082c74ad251Schristos }
1083c74ad251Schristos 
1084c74ad251Schristos static void
1085c74ad251Schristos print_attr_mip6_home_link_prefix(netdissect_options *ndo,
1086c74ad251Schristos                     const u_char *data, u_int length, u_short attr_code _U_)
1087c74ad251Schristos {
1088*26ba0b50Schristos    if (length != 17) {
1089c74ad251Schristos       ND_PRINT("ERROR: length %u != 17", length);
1090c74ad251Schristos       return;
1091c74ad251Schristos    }
1092c74ad251Schristos    ND_TCHECK_LEN(data, length);
1093*26ba0b50Schristos    if (GET_U_1(data) > 128) {
1094c74ad251Schristos       ND_PRINT("ERROR: netmask %u not in range (0..128)", GET_U_1(data));
1095c74ad251Schristos       return;
1096c74ad251Schristos    }
1097c74ad251Schristos 
1098c74ad251Schristos    ND_PRINT("%s/%u", GET_IP6ADDR_STRING(data + 1), GET_U_1(data));
1099c74ad251Schristos 
1100c74ad251Schristos    return;
1101c74ad251Schristos 
1102c74ad251Schristos    trunc:
1103c74ad251Schristos      nd_print_trunc(ndo);
1104c74ad251Schristos }
1105c74ad251Schristos 
1106c74ad251Schristos static void
1107c74ad251Schristos print_attr_operator_name(netdissect_options *ndo,
1108c74ad251Schristos                     const u_char *data, u_int length, u_short attr_code _U_)
1109c74ad251Schristos {
1110c74ad251Schristos    u_int namespace_value;
1111c74ad251Schristos 
1112c74ad251Schristos    ND_TCHECK_LEN(data, length);
1113*26ba0b50Schristos    if (length < 2) {
1114c74ad251Schristos       ND_PRINT("ERROR: length %u < 2", length);
1115c74ad251Schristos       return;
1116c74ad251Schristos    }
1117c74ad251Schristos    namespace_value = GET_U_1(data);
1118c74ad251Schristos    data++;
1119c74ad251Schristos    ND_PRINT("[%s] ", tok2str(operator_name_vector, "unknown namespace %u", namespace_value));
1120c74ad251Schristos 
1121c74ad251Schristos    (void)nd_printn(ndo, data, length - 1, NULL);
1122c74ad251Schristos 
1123c74ad251Schristos    return;
1124c74ad251Schristos 
1125c74ad251Schristos    trunc:
1126c74ad251Schristos       nd_print_trunc(ndo);
1127c74ad251Schristos }
1128c74ad251Schristos 
1129c74ad251Schristos static void
1130c74ad251Schristos print_attr_location_information(netdissect_options *ndo,
1131c74ad251Schristos                     const u_char *data, u_int length, u_short attr_code _U_)
1132c74ad251Schristos {
1133c74ad251Schristos    uint16_t index;
1134c74ad251Schristos    uint8_t code, entity;
1135c74ad251Schristos 
1136c74ad251Schristos    ND_TCHECK_LEN(data, length);
1137*26ba0b50Schristos    if (length < 21) {
1138c74ad251Schristos      ND_PRINT("ERROR: length %u < 21", length);
1139c74ad251Schristos       return;
1140c74ad251Schristos    }
1141c74ad251Schristos 
1142c74ad251Schristos    index = GET_BE_U_2(data);
1143c74ad251Schristos    data += 2;
1144c74ad251Schristos 
1145c74ad251Schristos    code = GET_U_1(data);
1146c74ad251Schristos    data++;
1147c74ad251Schristos 
1148c74ad251Schristos    entity = GET_U_1(data);
1149c74ad251Schristos    data++;
1150c74ad251Schristos 
1151c74ad251Schristos    ND_PRINT("index %u, code %s, entity %s, ",
1152c74ad251Schristos        index,
1153c74ad251Schristos        tok2str(location_information_code_vector, "Unknown (%u)", code),
1154c74ad251Schristos        tok2str(location_information_entity_vector, "Unknown (%u)", entity)
1155c74ad251Schristos    );
1156c74ad251Schristos 
1157c74ad251Schristos    ND_PRINT("sighting time ");
1158c74ad251Schristos    p_ntp_time(ndo, (const struct l_fixedpt *)data);
1159c74ad251Schristos    ND_PRINT(", ");
1160c74ad251Schristos    data += 8;
1161c74ad251Schristos 
1162c74ad251Schristos    ND_PRINT("time to live ");
1163c74ad251Schristos    p_ntp_time(ndo, (const struct l_fixedpt *)data);
1164c74ad251Schristos    ND_PRINT(", ");
1165c74ad251Schristos    data += 8;
1166c74ad251Schristos 
1167c74ad251Schristos    ND_PRINT("method \"");
1168c74ad251Schristos    (void)nd_printn(ndo, data, length - 20, NULL);
1169c74ad251Schristos    ND_PRINT("\"");
1170c74ad251Schristos 
1171c74ad251Schristos    return;
1172c74ad251Schristos 
1173c74ad251Schristos    trunc:
1174c74ad251Schristos       nd_print_trunc(ndo);
1175c74ad251Schristos }
1176c74ad251Schristos 
1177c74ad251Schristos static void
1178c74ad251Schristos print_attr_location_data(netdissect_options *ndo,
1179c74ad251Schristos                     const u_char *data, u_int length, u_short attr_code _U_)
1180c74ad251Schristos {
1181c74ad251Schristos    uint16_t index;
1182c74ad251Schristos 
1183c74ad251Schristos    ND_TCHECK_LEN(data, length);
1184*26ba0b50Schristos    if (length < 3) {
1185c74ad251Schristos      ND_PRINT("ERROR: length %u < 3", length);
1186c74ad251Schristos       return;
1187c74ad251Schristos    }
1188c74ad251Schristos 
1189c74ad251Schristos    index = GET_BE_U_2(data);
1190c74ad251Schristos    data += 2;
1191c74ad251Schristos    ND_PRINT("index %u, location", index);
1192c74ad251Schristos 
1193c74ad251Schristos    /* The Location field of the String field of the Location-Data attribute
1194c74ad251Schristos     * can have two completely different structures depending on the value of
1195c74ad251Schristos     * the Code field of a Location-Info attribute, which supposedly precedes
1196c74ad251Schristos     * the current attribute. Unfortunately, this choice of encoding makes it
1197c74ad251Schristos     * non-trivial to decode the Location field without preserving some state
1198c74ad251Schristos     * between the attributes.
1199c74ad251Schristos     */
1200c74ad251Schristos    hex_and_ascii_print(ndo, "\n\t    ", data, length - 2);
1201c74ad251Schristos 
1202c74ad251Schristos    return;
1203c74ad251Schristos 
1204c74ad251Schristos    trunc:
1205c74ad251Schristos       nd_print_trunc(ndo);
1206c74ad251Schristos }
1207c74ad251Schristos 
1208c74ad251Schristos static void
1209c74ad251Schristos print_basic_location_policy_rules(netdissect_options *ndo,
1210c74ad251Schristos                     const u_char *data, u_int length, u_short attr_code _U_)
1211c74ad251Schristos {
1212c74ad251Schristos    uint16_t flags;
1213c74ad251Schristos 
1214c74ad251Schristos    ND_TCHECK_LEN(data, length);
1215*26ba0b50Schristos    if (length < 10) {
1216c74ad251Schristos      ND_PRINT("ERROR: length %u < 10", length);
1217c74ad251Schristos       return;
1218c74ad251Schristos    }
1219c74ad251Schristos 
1220c74ad251Schristos    flags = GET_BE_U_2(data);
1221c74ad251Schristos    data += 2;
1222c74ad251Schristos    ND_PRINT("flags [%s], ", bittok2str(blpr_bm, "none", flags));
1223c74ad251Schristos 
1224c74ad251Schristos    ND_PRINT("retention expires ");
1225c74ad251Schristos    p_ntp_time(ndo, (const struct l_fixedpt *)data);
1226c74ad251Schristos    data += 8;
1227c74ad251Schristos 
1228c74ad251Schristos    if (length > 10) {
1229c74ad251Schristos       ND_PRINT(", note well \"");
1230c74ad251Schristos       (void)nd_printn(ndo, data, length - 10, NULL);
1231c74ad251Schristos       ND_PRINT("\"");
1232c74ad251Schristos    }
12330f74e101Schristos 
12340f74e101Schristos    return;
12350f74e101Schristos 
12360f74e101Schristos    trunc:
1237c74ad251Schristos       nd_print_trunc(ndo);
12380f74e101Schristos }
12390f74e101Schristos 
1240c74ad251Schristos 
12410f74e101Schristos /*************************************/
12420f74e101Schristos /* Print an attribute of 'secs since */
12430f74e101Schristos /* January 1, 1970 00:00 UTC' value  */
12440f74e101Schristos /* pointed by 'data' and 'length'    */
12450f74e101Schristos /* size.                             */
12460f74e101Schristos /*************************************/
12470f74e101Schristos /* Returns nothing.                  */
12480f74e101Schristos /*************************************/
1249b3a00663Schristos static void
1250b3a00663Schristos print_attr_time(netdissect_options *ndo,
1251c74ad251Schristos                 const u_char *data, u_int length, u_short attr_code _U_)
12520f74e101Schristos {
12530f74e101Schristos    time_t attr_time;
12540f74e101Schristos    char string[26];
12550f74e101Schristos 
1256*26ba0b50Schristos    if (length != 4) {
1257c74ad251Schristos        ND_PRINT("ERROR: length %u != 4", length);
12580f74e101Schristos        return;
12590f74e101Schristos    }
12600f74e101Schristos 
1261c74ad251Schristos    attr_time = GET_BE_U_4(data);
1262c74ad251Schristos    strlcpy(string, ctime(&attr_time), sizeof(string));
12630f74e101Schristos    /* Get rid of the newline */
12640f74e101Schristos    string[24] = '\0';
1265c74ad251Schristos    ND_PRINT("%.24s", string);
1266c74ad251Schristos }
12670f74e101Schristos 
1268c74ad251Schristos static void
1269c74ad251Schristos print_attr_vector64(netdissect_options *ndo,
1270*26ba0b50Schristos 		    const u_char *data, u_int length, u_short attr_code _U_)
1271c74ad251Schristos {
1272c74ad251Schristos    uint64_t data_value, i;
1273c74ad251Schristos    const char *sep = "";
1274c74ad251Schristos 
1275*26ba0b50Schristos    if (length != 8) {
1276c74ad251Schristos        ND_PRINT("ERROR: length %u != 8", length);
1277c74ad251Schristos        return;
1278c74ad251Schristos    }
1279c74ad251Schristos 
1280c74ad251Schristos    ND_PRINT("[");
1281c74ad251Schristos 
1282c74ad251Schristos    data_value = GET_BE_U_8(data);
1283c74ad251Schristos    /* Print the 64-bit field in a format similar to bittok2str(), less
1284c74ad251Schristos     * flagging any unknown bits. This way it should be easier to replace
1285c74ad251Schristos     * the custom code with a library function later.
1286c74ad251Schristos     */
1287c74ad251Schristos    for (i = 0; i < TAM_SIZE(mip6_feature_vector); i++) {
1288c74ad251Schristos        if (data_value & mip6_feature_vector[i].v) {
1289c74ad251Schristos            ND_PRINT("%s%s", sep, mip6_feature_vector[i].s);
1290c74ad251Schristos            sep = ", ";
1291c74ad251Schristos        }
1292c74ad251Schristos    }
1293c74ad251Schristos 
1294c74ad251Schristos    ND_PRINT("]");
12950f74e101Schristos }
12960f74e101Schristos 
12970f74e101Schristos /***********************************/
12980f74e101Schristos /* Print an attribute of 'strange' */
12990f74e101Schristos /* data format pointed by 'data'   */
13000f74e101Schristos /* and 'length' size.              */
13010f74e101Schristos /***********************************/
13020f74e101Schristos /* Returns nothing.                */
13030f74e101Schristos /***********************************/
1304b3a00663Schristos static void
1305b3a00663Schristos print_attr_strange(netdissect_options *ndo,
1306c74ad251Schristos                    const u_char *data, u_int length, u_short attr_code)
13070f74e101Schristos {
13080f74e101Schristos    u_short len_data;
1309c74ad251Schristos    u_int error_cause_value;
13100f74e101Schristos 
1311*26ba0b50Schristos    switch(attr_code) {
13120f74e101Schristos       case ARAP_PASS:
1313*26ba0b50Schristos            if (length != 16) {
1314c74ad251Schristos                ND_PRINT("ERROR: length %u != 16", length);
13150f74e101Schristos                return;
13160f74e101Schristos            }
1317c74ad251Schristos            ND_PRINT("User_challenge (");
13180f74e101Schristos            len_data = 8;
13190f74e101Schristos            PRINT_HEX(len_data, data);
1320c74ad251Schristos            ND_PRINT(") User_resp(");
13210f74e101Schristos            len_data = 8;
13220f74e101Schristos            PRINT_HEX(len_data, data);
1323c74ad251Schristos            ND_PRINT(")");
13240f74e101Schristos         break;
13250f74e101Schristos 
13260f74e101Schristos       case ARAP_FEATURES:
1327*26ba0b50Schristos            if (length != 14) {
1328c74ad251Schristos                ND_PRINT("ERROR: length %u != 14", length);
13290f74e101Schristos                return;
13300f74e101Schristos            }
1331c74ad251Schristos            if (GET_U_1(data))
1332c74ad251Schristos               ND_PRINT("User can change password");
13330f74e101Schristos            else
1334c74ad251Schristos               ND_PRINT("User cannot change password");
13350f74e101Schristos            data++;
1336c74ad251Schristos            ND_PRINT(", Min password length: %u", GET_U_1(data));
13370f74e101Schristos            data++;
1338c74ad251Schristos            ND_PRINT(", created at: ");
13390f74e101Schristos            len_data = 4;
13400f74e101Schristos            PRINT_HEX(len_data, data);
1341c74ad251Schristos            ND_PRINT(", expires in: ");
13420f74e101Schristos            len_data = 4;
13430f74e101Schristos            PRINT_HEX(len_data, data);
1344c74ad251Schristos            ND_PRINT(", Current Time: ");
13450f74e101Schristos            len_data = 4;
13460f74e101Schristos            PRINT_HEX(len_data, data);
13470f74e101Schristos         break;
13480f74e101Schristos 
13490f74e101Schristos       case ARAP_CHALLENGE_RESP:
1350*26ba0b50Schristos            if (length < 8) {
1351c74ad251Schristos                ND_PRINT("ERROR: length %u != 8", length);
13520f74e101Schristos                return;
13530f74e101Schristos            }
13540f74e101Schristos            len_data = 8;
13550f74e101Schristos            PRINT_HEX(len_data, data);
13560f74e101Schristos         break;
1357c74ad251Schristos 
1358c74ad251Schristos       case ERROR_CAUSE:
1359*26ba0b50Schristos            if (length != 4) {
1360c74ad251Schristos                ND_PRINT("Error: length %u != 4", length);
1361c74ad251Schristos                return;
1362c74ad251Schristos            }
1363c74ad251Schristos 
1364c74ad251Schristos            error_cause_value = GET_BE_U_4(data);
1365c74ad251Schristos            ND_PRINT("Error cause %u: %s", error_cause_value, tok2str(errorcausetype, "Error-Cause %u not known", error_cause_value));
1366c74ad251Schristos         break;
13670f74e101Schristos    }
13680f74e101Schristos    return;
13690f74e101Schristos }
13700f74e101Schristos 
13710f74e101Schristos static void
1372b3a00663Schristos radius_attrs_print(netdissect_options *ndo,
1373c74ad251Schristos                    const u_char *attr, u_int length)
13740f74e101Schristos {
1375c74ad251Schristos    const struct radius_attr *rad_attr = (const struct radius_attr *)attr;
13760f74e101Schristos    const char *attr_string;
1377c74ad251Schristos    uint8_t type, len;
13780f74e101Schristos 
1379*26ba0b50Schristos    while (length > 0) {
13800f74e101Schristos      if (length < 2)
13810f74e101Schristos         goto trunc;
1382c74ad251Schristos      ND_TCHECK_SIZE(rad_attr);
13830f74e101Schristos 
1384c74ad251Schristos      type = GET_U_1(rad_attr->type);
1385c74ad251Schristos      len = GET_U_1(rad_attr->len);
1386c74ad251Schristos      if (type != 0 && type < TAM_SIZE(attr_type))
1387c74ad251Schristos 	attr_string = attr_type[type].name;
13880f74e101Schristos      else
13890f74e101Schristos 	attr_string = "Unknown";
13900f74e101Schristos 
1391c74ad251Schristos      ND_PRINT("\n\t  %s Attribute (%u), length: %u",
1392c74ad251Schristos                attr_string,
1393c74ad251Schristos                type,
1394c74ad251Schristos                len);
1395*26ba0b50Schristos      if (len < 2) {
1396c74ad251Schristos        ND_PRINT(" (bogus, must be >= 2)");
1397c74ad251Schristos        return;
1398c74ad251Schristos      }
1399*26ba0b50Schristos      if (len > length) {
1400c74ad251Schristos         ND_PRINT(" (bogus, goes past end of packet)");
1401c74ad251Schristos         return;
1402c74ad251Schristos      }
1403c74ad251Schristos      ND_PRINT(", Value: ");
1404c74ad251Schristos 
1405*26ba0b50Schristos      if (type < TAM_SIZE(attr_type)) {
1406*26ba0b50Schristos          if (len > 2) {
1407c74ad251Schristos              if ( attr_type[type].print_func )
1408c74ad251Schristos                  (*attr_type[type].print_func)(
1409fdccd7e4Schristos                      ndo, ((const u_char *)(rad_attr+1)),
1410c74ad251Schristos                      len - 2, type);
14110f74e101Schristos          }
14120f74e101Schristos      }
14130f74e101Schristos      /* do we also want to see a hex dump ? */
1414b3a00663Schristos      if (ndo->ndo_vflag> 1)
1415c74ad251Schristos          print_unknown_data(ndo, (const u_char *)rad_attr+2, "\n\t    ", (len)-2);
14160f74e101Schristos 
1417c74ad251Schristos      length-=(len);
1418c74ad251Schristos      rad_attr = (const struct radius_attr *)( ((const char *)(rad_attr))+len);
14190f74e101Schristos    }
14200f74e101Schristos    return;
14210f74e101Schristos 
14220f74e101Schristos trunc:
1423c74ad251Schristos    nd_print_trunc(ndo);
14240f74e101Schristos }
14250f74e101Schristos 
14260f74e101Schristos void
1427b3a00663Schristos radius_print(netdissect_options *ndo,
1428b3a00663Schristos              const u_char *dat, u_int length)
14290f74e101Schristos {
1430c74ad251Schristos    const struct radius_hdr *rad;
14310f74e101Schristos    u_int len, auth_idx;
14320f74e101Schristos 
1433c74ad251Schristos    ndo->ndo_protocol = "radius";
1434c74ad251Schristos    ND_TCHECK_LEN(dat, MIN_RADIUS_LEN);
1435fdccd7e4Schristos    rad = (const struct radius_hdr *)dat;
1436c74ad251Schristos    len = GET_BE_U_2(rad->len);
14370f74e101Schristos 
1438*26ba0b50Schristos    if (len < MIN_RADIUS_LEN) {
1439c74ad251Schristos 	  nd_print_trunc(ndo);
14400f74e101Schristos 	  return;
14410f74e101Schristos    }
14420f74e101Schristos 
14430f74e101Schristos    if (len > length)
14440f74e101Schristos 	  len = length;
14450f74e101Schristos 
1446b3a00663Schristos    if (ndo->ndo_vflag < 1) {
1447c74ad251Schristos        ND_PRINT("RADIUS, %s (%u), id: 0x%02x length: %u",
1448c74ad251Schristos               tok2str(radius_command_values,"Unknown Command",GET_U_1(rad->code)),
1449c74ad251Schristos               GET_U_1(rad->code),
1450c74ad251Schristos               GET_U_1(rad->id),
1451c74ad251Schristos               len);
14520f74e101Schristos        return;
1453*26ba0b50Schristos    } else {
1454c74ad251Schristos        ND_PRINT("RADIUS, length: %u\n\t%s (%u), id: 0x%02x, Authenticator: ",
14550f74e101Schristos               len,
1456c74ad251Schristos               tok2str(radius_command_values,"Unknown Command",GET_U_1(rad->code)),
1457c74ad251Schristos               GET_U_1(rad->code),
1458c74ad251Schristos               GET_U_1(rad->id));
14590f74e101Schristos 
14600f74e101Schristos        for(auth_idx=0; auth_idx < 16; auth_idx++)
1461c74ad251Schristos             ND_PRINT("%02x", rad->auth[auth_idx]);
14620f74e101Schristos    }
14630f74e101Schristos 
14640f74e101Schristos    if (len > MIN_RADIUS_LEN)
1465b3a00663Schristos       radius_attrs_print(ndo, dat + MIN_RADIUS_LEN, len - MIN_RADIUS_LEN);
14660f74e101Schristos    return;
14670f74e101Schristos 
14680f74e101Schristos trunc:
1469c74ad251Schristos    nd_print_trunc(ndo);
14700f74e101Schristos }
1471