]> The Tcpdump Group git mirrors - tcpdump/blobdiff - print-radius.c
NTP: Use tstr for truncation indicator.
[tcpdump] / print-radius.c
index 86e9cd896c75604f3a4a08a682abff8b86d1b0cc..eb48de5059bd1fc4f9368477aa09b0614df068f9 100644 (file)
@@ -1,3 +1,27 @@
+/*
+ * Copyright (C) 2000 Alfredo Andres Omella.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in
+ *      the documentation and/or other materials provided with the
+ *      distribution.
+ *   3. The names of the authors may not be used to endorse or promote
+ *      products derived from this software without specific prior
+ *      written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/* \summary: Radius protocol printer */
+
 /*
  * Radius printer routines as specified on:
  *
  * RFC 2869:
  *      "RADIUS Extensions"
  *
+ * RFC 3580:
+ *      "IEEE 802.1X Remote Authentication Dial In User Service (RADIUS)"
+ *      "Usage Guidelines"
+ *
+ * RFC 4675:
+ *      "RADIUS Attributes for Virtual LAN and Priority Support"
+ *
+ * RFC 5176:
+ *      "Dynamic Authorization Extensions to RADIUS"
+ *
  * Alfredo Andres Omella ([email protected]) v0.1 2000/09/15
  *
- * TODO: Among other things to print ok MacIntosh and Vendor values 
+ * TODO: Among other things to print ok MacIntosh and Vendor values
  */
 
-#ifndef lint
-static const char rcsid[] =
-    "$Id: print-radius.c,v 1.9 2001-07-15 19:27:45 guy Exp $";
-#endif
-
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
 
-#include <string.h>
-
-#include <sys/param.h>
-
-#include <netinet/in.h>
+#include <netdissect-stdinc.h>
 
-#include <stdio.h>
+#include <string.h>
 
-#include "interface.h"
+#include "netdissect.h"
 #include "addrtoname.h"
 #include "extract.h"
+#include "oui.h"
+
+static const char tstr[] = " [|radius]";
 
 #define TAM_SIZE(x) (sizeof(x)/sizeof(x[0]) )
 
 #define PRINT_HEX(bytes_len, ptr_data)                               \
            while(bytes_len)                                          \
            {                                                         \
-              printf("%02X", *ptr_data );                            \
+              ND_PRINT((ndo, "%02X", *ptr_data ));                   \
               ptr_data++;                                            \
               bytes_len--;                                           \
            }
@@ -62,8 +90,32 @@ static const char rcsid[] =
 #define RADCMD_ACCESS_CHA  11 /* Access-Challenge    */
 #define RADCMD_STATUS_SER  12 /* Status-Server       */
 #define RADCMD_STATUS_CLI  13 /* Status-Client       */
+#define RADCMD_DISCON_REQ  40 /* Disconnect-Request  */
+#define RADCMD_DISCON_ACK  41 /* Disconnect-ACK      */
+#define RADCMD_DISCON_NAK  42 /* Disconnect-NAK      */
+#define RADCMD_COA_REQ     43 /* CoA-Request         */
+#define RADCMD_COA_ACK     44 /* CoA-ACK             */
+#define RADCMD_COA_NAK     45 /* CoA-NAK             */
 #define RADCMD_RESERVED   255 /* Reserved            */
 
+static const struct tok radius_command_values[] = {
+    { RADCMD_ACCESS_REQ, "Access-Request" },
+    { RADCMD_ACCESS_ACC, "Access-Accept" },
+    { RADCMD_ACCESS_REJ, "Access-Reject" },
+    { RADCMD_ACCOUN_REQ, "Accounting-Request" },
+    { RADCMD_ACCOUN_RES, "Accounting-Response" },
+    { RADCMD_ACCESS_CHA, "Access-Challenge" },
+    { RADCMD_STATUS_SER, "Status-Server" },
+    { RADCMD_STATUS_CLI, "Status-Client" },
+    { RADCMD_DISCON_REQ, "Disconnect-Request" },
+    { RADCMD_DISCON_ACK, "Disconnect-ACK" },
+    { RADCMD_DISCON_NAK, "Disconnect-NAK" },
+    { RADCMD_COA_REQ,    "CoA-Request" },
+    { RADCMD_COA_ACK,    "CoA-ACK" },
+    { RADCMD_COA_NAK,    "CoA-NAK" },
+    { RADCMD_RESERVED,   "Reserved" },
+    { 0, NULL}
+};
 
 /********************************/
 /* Begin Radius Attribute types */
@@ -81,6 +133,9 @@ static const char rcsid[] =
 #define ACCT_DELAY        41
 #define ACCT_SESSION_TIME 46
 
+#define EGRESS_VLAN_ID   56
+#define EGRESS_VLAN_NAME 58
+
 #define TUNNEL_TYPE        64
 #define TUNNEL_MEDIUM      65
 #define TUNNEL_CLIENT_END  66
@@ -103,41 +158,51 @@ static const char rcsid[] =
 /* End Radius Attribute types */
 /********************************/
 
+#define RFC4675_TAGGED   0x31
+#define RFC4675_UNTAGGED 0x32
+
+static const struct tok rfc4675_tagged[] = {
+    { RFC4675_TAGGED,   "Tagged" },
+    { RFC4675_UNTAGGED, "Untagged" },
+    { 0, NULL}
+};
 
-static void print_attr_string(register u_char *, u_int, u_short );
-static void print_attr_num(register u_char *, u_int, u_short );
-static void print_attr_address(register u_char *, u_int, u_short);
-static void print_attr_time(register u_char *, u_int, u_short);
-static void print_attr_strange(register u_char *, u_int, u_short);
 
+static void print_attr_string(netdissect_options *, register const u_char *, u_int, u_short );
+static void print_attr_num(netdissect_options *, register const u_char *, u_int, u_short );
+static void print_vendor_attr(netdissect_options *, register const u_char *, u_int, u_short );
+static void print_attr_address(netdissect_options *, register const u_char *, u_int, u_short);
+static void print_attr_time(netdissect_options *, register const u_char *, u_int, u_short);
+static void print_attr_strange(netdissect_options *, register const u_char *, u_int, u_short);
 
-struct radius_hdr { u_int8_t  code; /* Radius packet code  */
-                    u_int8_t  id;   /* Radius packet id    */
-                    u_int16_t len;  /* Radius total length */
-                    u_int8_t  auth[16]; /* Authenticator   */
+
+struct radius_hdr { uint8_t  code; /* Radius packet code  */
+                    uint8_t  id;   /* Radius packet id    */
+                    uint16_t len;  /* Radius total length */
+                    uint8_t  auth[16]; /* Authenticator   */
                   };
 
 #define MIN_RADIUS_LEN 20
 
-struct radius_attr { u_int8_t type; /* Attribute type   */
-                     u_int8_t len;  /* Attribute length */
+struct radius_attr { uint8_t type; /* Attribute type   */
+                     uint8_t len;  /* Attribute length */
                    };
 
 
-/* Service-Type Attribute standard values */                 
+/* Service-Type Attribute standard values */
 static const char *serv_type[]={ NULL,
                                 "Login",
-                                "Framed",  
+                                "Framed",
                                 "Callback Login",
                                 "Callback Framed",
                                 "Outbound",
                                 "Administrative",
-                                "NAS Prompt",                            
+                                "NAS Prompt",
                                 "Authenticate Only",
                                 "Callback NAS Prompt",
                                 "Call Check",
                                 "Callback Administrative",
-                               };                               
+                               };
 
 /* Framed-Protocol Attribute standard values */
 static const char *frm_proto[]={ NULL,
@@ -147,14 +212,14 @@ static const char *frm_proto[]={ NULL,
                                  "Gandalf proprietary",
                                  "Xylogics IPX/SLIP",
                                  "X.75 Synchronous",
-                               };                               
+                               };
 
 /* Framed-Routing Attribute standard values */
 static const char *frm_routing[]={ "None",
                                    "Send",
                                    "Listen",
                                    "Send&Listen",
-                                 };                               
+                                 };
 
 /* Framed-Compression Attribute standard values */
 static const char *frm_comp[]={ "None",
@@ -181,6 +246,12 @@ static const char *term_action[]={ "Default",
                                    "RADIUS-Request",
                                  };
 
+/* Ingress-Filters Attribute standard values */
+static const char *ingress_filters[]={ NULL,
+                                       "Enabled",
+                                       "Disabled",
+                                     };
+
 /* NAS-Port-Type Attribute standard values */
 static const char *nas_port_type[]={ "Async",
                                      "Sync",
@@ -202,7 +273,7 @@ static const char *nas_port_type[]={ "Async",
                                      "Cable",
                                      "Wireless - Other",
                                      "Wireless - IEEE 802.11",
-                                   };         
+                                   };
 
 /* Acct-Status-Type Accounting Attribute standard values */
 static const char *acct_status[]={ NULL,
@@ -266,8 +337,9 @@ static const char *tunnel_type[]={ NULL,
                                    "GRE",
                                    "DVS",
                                    "IP-in-IP Tunneling",
+                                   "VLAN",
                                  };
-                                   
+
 /* Tunnel-Medium-Type Attribute standard values */
 static const char *tunnel_medium[]={ NULL,
                                      "IPv4",
@@ -298,114 +370,111 @@ static const char *arap_zone[]={ NULL,
 static const char *prompt[]={ "No Echo",
                               "Echo",
                             };
-                            
-                                                               
-struct attrtype { char *name;            /* Attribute name                 */
+
+
+static struct attrtype {
+                  const char *name;      /* Attribute name                 */
                   const char **subtypes; /* Standard Values (if any)       */
                   u_char siz_subtypes;   /* Size of total standard values  */
                   u_char first_subtype;  /* First standard value is 0 or 1 */
-                  void (*print_func)(register u_char *, u_int, u_short );
+                  void (*print_func)(netdissect_options *, register const u_char *, u_int, u_short);
                 } attr_type[]=
   {
-     { NULL,             NULL, 0, 0, NULL               },
-     { "User",           NULL, 0, 0, print_attr_string  },
-     { "Pass",           NULL, 0, 0, NULL               },
-     { "CHAP-Pass",      NULL, 0, 0, NULL               },
-     { "NAS_ipaddr",     NULL, 0, 0, print_attr_address },
-     { "NAS_port",       NULL, 0, 0, print_attr_num     },
-     { "Service_type",   serv_type, TAM_SIZE(serv_type)-1, 1, print_attr_num },                 
-     { "Framed_proto",   frm_proto, TAM_SIZE(frm_proto)-1, 1, print_attr_num },
-     { "Framed_ipaddr",  NULL, 0, 0, print_attr_address },
-     { "Framed_ipnet",   NULL, 0, 0, print_attr_address },
-     { "Framed_routing", frm_routing, TAM_SIZE(frm_routing), 0, 
-                                                              print_attr_num }, 
-     { "Filter_id",      NULL, 0, 0, print_attr_string  },
-     { "Framed_mtu",     NULL, 0, 0, print_attr_num     },
-     { "Framed_compress",  frm_comp, TAM_SIZE(frm_comp),   0, print_attr_num },
-     { "Login_iphost",   NULL, 0, 0, print_attr_address },
-     { "Login_service",  login_serv, TAM_SIZE(login_serv), 0, print_attr_num },
-     { "Login_TCP_port", NULL, 0, 0, print_attr_num     },                 
-/*17*/ { "Unassigned", NULL, 0, 0, NULL },                 
-     { "Reply",           NULL, 0, 0, print_attr_string },
-     { "Callback-number", NULL, 0, 0, print_attr_string },
-     { "Callback-id",     NULL, 0, 0, print_attr_string },
-/*21*/ { "Unassigned", NULL, 0, 0, NULL },   
-     { "Framed_route",      NULL, 0, 0, print_attr_string },
-     { "Framed_ipx_net",    NULL, 0, 0, print_attr_num    },
-     { "State",             NULL, 0, 0, print_attr_string },
-     { "Class",             NULL, 0, 0, print_attr_string },
-     { "Vendor_specific",   NULL, 0, 0, print_attr_string },
-     { "Session_timeout",   NULL, 0, 0, print_attr_num    },
-     { "Idle_timeout",      NULL, 0, 0, print_attr_num    },
-     { "Term_action", term_action, TAM_SIZE(term_action), 0, print_attr_num },
-     { "Called_station",    NULL, 0, 0, print_attr_string },
-     { "Calling_station",   NULL, 0, 0, print_attr_string },   
-     { "NAS_id",            NULL, 0, 0, print_attr_string },
-     { "Proxy_state",       NULL, 0, 0, print_attr_string },
-     { "Login_LAT_service", NULL, 0, 0, print_attr_string },
-     { "Login_LAT_node",    NULL, 0, 0, print_attr_string },
-     { "Login_LAT_group",   NULL, 0, 0, print_attr_string },
-     { "Framed_atalk_link", NULL, 0, 0, print_attr_num    },
-     { "Framed_atalk_net",  NULL, 0, 0, print_attr_num    },
-     { "Framed_atalk_zone", NULL, 0, 0, print_attr_string },
-     { "Acct_status", acct_status, TAM_SIZE(acct_status)-1, 1, print_attr_num },
-     { "Acct_delay",        NULL, 0, 0, print_attr_num    },
-     { "Acct_in_octets",    NULL, 0, 0, print_attr_num    },
-     { "Acct_out_octets",   NULL, 0, 0, print_attr_num    },
-     { "Acct_session_id",   NULL, 0, 0, print_attr_string },
-     { "Acct_authentic",  acct_auth, TAM_SIZE(acct_auth)-1, 1, print_attr_num },
-     { "Acct_session_time", NULL, 0, 0, print_attr_num },
-     { "Acct_in_packets",   NULL, 0, 0, print_attr_num },
-     { "Acct_out_packets",  NULL, 0, 0, print_attr_num },
-     { "Acct_term_cause", acct_term, TAM_SIZE(acct_term)-1, 1, print_attr_num },
-     { "Acct_multi_session_id", NULL, 0, 0, print_attr_string },
-     { "Acct_link_count", NULL, 0, 0, print_attr_num },
-     { "Acct_in_giga",    NULL, 0, 0, print_attr_num },
-     { "Acct_out_giga",   NULL, 0, 0, print_attr_num },
-/*54*/ { "Unassigned", NULL, 0, 0, NULL },
-     { "Event_timestamp", NULL, 0, 0, print_attr_time },
-/*56*/ { "Unassigned", NULL, 0, 0, NULL },
-/*57*/ { "Unassigned", NULL, 0, 0, NULL },
-/*58*/ { "Unassigned", NULL, 0, 0, NULL },
-/*59*/ { "Unassigned", NULL, 0, 0, NULL },
-     { "CHAP_challenge", NULL, 0, 0, print_attr_string },  
-     { "NAS_port_type",  nas_port_type, TAM_SIZE(nas_port_type), 0, 
-                                                              print_attr_num },
-     { "Port_limit",     NULL, 0, 0, print_attr_num },
-/*63*/ { "Login_LAT_port", NULL, 0, 0, print_attr_string },
-     { "Tunnel_type", tunnel_type, TAM_SIZE(tunnel_type)-1, 1, print_attr_num },
-     { "Tunnel_medium", tunnel_medium, TAM_SIZE(tunnel_medium)-1, 1, 
-                                                             print_attr_num },
-     { "Tunnel_client_end",   NULL, 0, 0, print_attr_string },
-     { "Tunnel_server_end",   NULL, 0, 0, print_attr_string },
-     { "Acct_tunnel_connect", NULL, 0, 0, print_attr_string },
-     { "Tunnel_pass",  NULL, 0, 0, print_attr_string  },
-     { "ARAP_pass",    NULL, 0, 0, print_attr_strange },
-     { "ARAP_feature", NULL, 0, 0, print_attr_strange },
-/*72*/ { "ARAP_zone_acces", arap_zone, TAM_SIZE(arap_zone)-1, 1, 
-                                                             print_attr_num },
-     { "ARAP_security",      NULL, 0, 0, print_attr_string },
-     { "ARAP_security_data", NULL, 0, 0, print_attr_string },
-     { "Password_retry",     NULL, 0, 0, print_attr_num    },
-     { "Prompt", prompt, TAM_SIZE(prompt), 0, print_attr_num },
-     { "Connect_info",       NULL, 0, 0, print_attr_string   },
-     { "Config_token",       NULL, 0, 0, print_attr_string   },
-     { "EAP_msg",            NULL, 0, 0, print_attr_string   },
-/*80*/ { "Message_auth",    NULL, 0, 0, print_attr_string },
-     { "Tunnel_priv_group", NULL, 0, 0, print_attr_string },
-     { "Tunnel_assign_id",  NULL, 0, 0, print_attr_string },
-     { "Tunnel_pref",       NULL, 0, 0, print_attr_num    },
-     { "ARAP_challenge_resp",    NULL, 0, 0, print_attr_strange },
-     { "Acct_interim_interval",  NULL, 0, 0, print_attr_num     },
-/*86*/ { "Acct_tunnel_pack_lost",  NULL, 0, 0, print_attr_num },
-     { "NAS_port_id", NULL, 0, 0, print_attr_string },
-     { "Framed_pool", NULL, 0, 0, print_attr_string },
-     { "Unassigned",  NULL, 0, 0, NULL },
-     { "Tunnel_client_auth_id", NULL, 0, 0, print_attr_string },
-     { "Tunnel_server_auth_id", NULL, 0, 0, print_attr_string },
-/*92*/ { "Unassigned",  NULL, 0, 0, NULL },
-/*93*/ { "Unassigned",  NULL, 0, 0, NULL }
-  };                    
+     { NULL,                              NULL, 0, 0, NULL               },
+     { "User-Name",                       NULL, 0, 0, print_attr_string  },
+     { "User-Password",                   NULL, 0, 0, NULL               },
+     { "CHAP-Password",                   NULL, 0, 0, NULL               },
+     { "NAS-IP-Address",                  NULL, 0, 0, print_attr_address },
+     { "NAS-Port",                        NULL, 0, 0, print_attr_num     },
+     { "Service-Type",                    serv_type, TAM_SIZE(serv_type)-1, 1, print_attr_num },
+     { "Framed-Protocol",                 frm_proto, TAM_SIZE(frm_proto)-1, 1, print_attr_num },
+     { "Framed-IP-Address",               NULL, 0, 0, print_attr_address },
+     { "Framed-IP-Netmask",               NULL, 0, 0, print_attr_address },
+     { "Framed-Routing",                  frm_routing, TAM_SIZE(frm_routing), 0, print_attr_num },
+     { "Filter-Id",                       NULL, 0, 0, print_attr_string  },
+     { "Framed-MTU",                      NULL, 0, 0, print_attr_num     },
+     { "Framed-Compression",              frm_comp, TAM_SIZE(frm_comp),   0, print_attr_num },
+     { "Login-IP-Host",                   NULL, 0, 0, print_attr_address },
+     { "Login-Service",                   login_serv, TAM_SIZE(login_serv), 0, print_attr_num },
+     { "Login-TCP-Port",                  NULL, 0, 0, print_attr_num     },
+     { "Unassigned",                      NULL, 0, 0, NULL }, /*17*/
+     { "Reply-Message",                   NULL, 0, 0, print_attr_string },
+     { "Callback-Number",                 NULL, 0, 0, print_attr_string },
+     { "Callback-Id",                     NULL, 0, 0, print_attr_string },
+     { "Unassigned",                      NULL, 0, 0, NULL }, /*21*/
+     { "Framed-Route",                    NULL, 0, 0, print_attr_string },
+     { "Framed-IPX-Network",              NULL, 0, 0, print_attr_num    },
+     { "State",                           NULL, 0, 0, print_attr_string },
+     { "Class",                           NULL, 0, 0, print_attr_string },
+     { "Vendor-Specific",                 NULL, 0, 0, print_vendor_attr },
+     { "Session-Timeout",                 NULL, 0, 0, print_attr_num    },
+     { "Idle-Timeout",                    NULL, 0, 0, print_attr_num    },
+     { "Termination-Action",              term_action, TAM_SIZE(term_action), 0, print_attr_num },
+     { "Called-Station-Id",               NULL, 0, 0, print_attr_string },
+     { "Calling-Station-Id",              NULL, 0, 0, print_attr_string },
+     { "NAS-Identifier",                  NULL, 0, 0, print_attr_string },
+     { "Proxy-State",                     NULL, 0, 0, print_attr_string },
+     { "Login-LAT-Service",               NULL, 0, 0, print_attr_string },
+     { "Login-LAT-Node",                  NULL, 0, 0, print_attr_string },
+     { "Login-LAT-Group",                 NULL, 0, 0, print_attr_string },
+     { "Framed-AppleTalk-Link",           NULL, 0, 0, print_attr_num    },
+     { "Framed-AppleTalk-Network",        NULL, 0, 0, print_attr_num    },
+     { "Framed-AppleTalk-Zone",           NULL, 0, 0, print_attr_string },
+     { "Acct-Status-Type",                acct_status, TAM_SIZE(acct_status)-1, 1, print_attr_num },
+     { "Acct-Delay-Time",                 NULL, 0, 0, print_attr_num    },
+     { "Acct-Input-Octets",               NULL, 0, 0, print_attr_num    },
+     { "Acct-Output-Octets",              NULL, 0, 0, print_attr_num    },
+     { "Acct-Session-Id",                 NULL, 0, 0, print_attr_string },
+     { "Acct-Authentic",                  acct_auth, TAM_SIZE(acct_auth)-1, 1, print_attr_num },
+     { "Acct-Session-Time",               NULL, 0, 0, print_attr_num },
+     { "Acct-Input-Packets",              NULL, 0, 0, print_attr_num },
+     { "Acct-Output-Packets",             NULL, 0, 0, print_attr_num },
+     { "Acct-Terminate-Cause",            acct_term, TAM_SIZE(acct_term)-1, 1, print_attr_num },
+     { "Acct-Multi-Session-Id",           NULL, 0, 0, print_attr_string },
+     { "Acct-Link-Count",                 NULL, 0, 0, print_attr_num },
+     { "Acct-Input-Gigawords",            NULL, 0, 0, print_attr_num },
+     { "Acct-Output-Gigawords",           NULL, 0, 0, print_attr_num },
+     { "Unassigned",                      NULL, 0, 0, NULL }, /*54*/
+     { "Event-Timestamp",                 NULL, 0, 0, print_attr_time },
+     { "Egress-VLANID",                   NULL, 0, 0, print_attr_num },
+     { "Ingress-Filters",                 ingress_filters, TAM_SIZE(ingress_filters)-1, 1, print_attr_num },
+     { "Egress-VLAN-Name",                NULL, 0, 0, print_attr_string },
+     { "User-Priority-Table",             NULL, 0, 0, NULL },
+     { "CHAP-Challenge",                  NULL, 0, 0, print_attr_string },
+     { "NAS-Port-Type",                   nas_port_type, TAM_SIZE(nas_port_type), 0, print_attr_num },
+     { "Port-Limit",                      NULL, 0, 0, print_attr_num },
+     { "Login-LAT-Port",                  NULL, 0, 0, print_attr_string }, /*63*/
+     { "Tunnel-Type",                     tunnel_type, TAM_SIZE(tunnel_type)-1, 1, print_attr_num },
+     { "Tunnel-Medium-Type",              tunnel_medium, TAM_SIZE(tunnel_medium)-1, 1, print_attr_num },
+     { "Tunnel-Client-Endpoint",          NULL, 0, 0, print_attr_string },
+     { "Tunnel-Server-Endpoint",          NULL, 0, 0, print_attr_string },
+     { "Acct-Tunnel-Connection",          NULL, 0, 0, print_attr_string },
+     { "Tunnel-Password",                 NULL, 0, 0, print_attr_string  },
+     { "ARAP-Password",                   NULL, 0, 0, print_attr_strange },
+     { "ARAP-Features",                   NULL, 0, 0, print_attr_strange },
+     { "ARAP-Zone-Access",                arap_zone, TAM_SIZE(arap_zone)-1, 1, print_attr_num }, /*72*/
+     { "ARAP-Security",                   NULL, 0, 0, print_attr_string },
+     { "ARAP-Security-Data",              NULL, 0, 0, print_attr_string },
+     { "Password-Retry",                  NULL, 0, 0, print_attr_num    },
+     { "Prompt",                          prompt, TAM_SIZE(prompt), 0, print_attr_num },
+     { "Connect-Info",                    NULL, 0, 0, print_attr_string   },
+     { "Configuration-Token",             NULL, 0, 0, print_attr_string   },
+     { "EAP-Message",                     NULL, 0, 0, print_attr_string   },
+     { "Message-Authenticator",           NULL, 0, 0, print_attr_string }, /*80*/
+     { "Tunnel-Private-Group-ID",         NULL, 0, 0, print_attr_string },
+     { "Tunnel-Assignment-ID",            NULL, 0, 0, print_attr_string },
+     { "Tunnel-Preference",               NULL, 0, 0, print_attr_num    },
+     { "ARAP-Challenge-Response",         NULL, 0, 0, print_attr_strange },
+     { "Acct-Interim-Interval",           NULL, 0, 0, print_attr_num     },
+     { "Acct-Tunnel-Packets-Lost",        NULL, 0, 0, print_attr_num }, /*86*/
+     { "NAS-Port-Id",                     NULL, 0, 0, print_attr_string },
+     { "Framed-Pool",                     NULL, 0, 0, print_attr_string },
+     { "CUI",                             NULL, 0, 0, print_attr_string },
+     { "Tunnel-Client-Auth-ID",           NULL, 0, 0, print_attr_string },
+     { "Tunnel-Server-Auth-ID",           NULL, 0, 0, print_attr_string },
+     { "Unassigned",                      NULL, 0, 0, NULL }, /*92*/
+     { "Unassigned",                      NULL, 0, 0, NULL }  /*93*/
+  };
 
 
 /*****************************/
@@ -416,20 +485,28 @@ struct attrtype { char *name;            /* Attribute name                 */
 /* Returns nothing.          */
 /*****************************/
 static void
-print_attr_string(register u_char *data, u_int length, u_short attr_code )
+print_attr_string(netdissect_options *ndo,
+                  register const u_char *data, u_int length, u_short attr_code)
 {
    register u_int i;
-   
-   TCHECK2(data[0],length);
-   
-   printf("{");
+
+   ND_TCHECK2(data[0],length);
+
    switch(attr_code)
    {
       case TUNNEL_PASS:
+           if (length < 3)
+           {
+              ND_PRINT((ndo, "%s", tstr));
+              return;
+           }
            if (*data && (*data <=0x1F) )
-              printf("Tag[%d] ",*data);
+              ND_PRINT((ndo, "Tag[%u] ", *data));
+           else
+              ND_PRINT((ndo, "Tag[Unused] "));
            data++;
-           printf("Salt[%d] ",EXTRACT_16BITS(data) );
+           length--;
+           ND_PRINT((ndo, "Salt %u ", EXTRACT_16BITS(data)));
            data+=2;
            length-=2;
         break;
@@ -441,24 +518,97 @@ print_attr_string(register u_char *data, u_int length, u_short attr_code )
       case TUNNEL_SERVER_AUTH:
            if (*data <= 0x1F)
            {
-              printf("Tag[%d] ",*data);
+              if (length < 1)
+              {
+                 ND_PRINT((ndo, "%s", tstr));
+                 return;
+              }
+              if (*data)
+                ND_PRINT((ndo, "Tag[%u] ", *data));
+              else
+                ND_PRINT((ndo, "Tag[Unused] "));
               data++;
               length--;
            }
         break;
+      case EGRESS_VLAN_NAME:
+           ND_PRINT((ndo, "%s (0x%02x) ",
+                  tok2str(rfc4675_tagged,"Unknown tag",*data),
+                  *data));
+           data++;
+           length--;
+        break;
    }
 
-   for (i=0; i < length ; i++, data++)
-       printf("%c",(*data < 32 || *data > 128) ? '.' : *data );
+   for (i=0; *data && i < length ; i++, data++)
+       ND_PRINT((ndo, "%c", (*data < 32 || *data > 126) ? '.' : *data));
 
-   printf("}");
-   
    return;
-   
+
    trunc:
-      printf("|radius");
-}  
+      ND_PRINT((ndo, "%s", tstr));
+}
+
+/*
+ * print vendor specific attributes
+ */
+static void
+print_vendor_attr(netdissect_options *ndo,
+                  register const u_char *data, u_int length, u_short attr_code _U_)
+{
+    u_int idx;
+    u_int vendor_id;
+    u_int vendor_type;
+    u_int vendor_length;
+
+    if (length < 4)
+        goto trunc;
+    ND_TCHECK2(*data, 4);
+    vendor_id = EXTRACT_32BITS(data);
+    data+=4;
+    length-=4;
 
+    ND_PRINT((ndo, "Vendor: %s (%u)",
+           tok2str(smi_values,"Unknown",vendor_id),
+           vendor_id));
+
+    while (length >= 2) {
+       ND_TCHECK2(*data, 2);
+
+        vendor_type = *(data);
+        vendor_length = *(data+1);
+
+        if (vendor_length < 2)
+        {
+            ND_PRINT((ndo, "\n\t    Vendor Attribute: %u, Length: %u (bogus, must be >= 2)",
+                   vendor_type,
+                   vendor_length));
+            return;
+        }
+        if (vendor_length > length)
+        {
+            ND_PRINT((ndo, "\n\t    Vendor Attribute: %u, Length: %u (bogus, goes past end of vendor-specific attribute)",
+                   vendor_type,
+                   vendor_length));
+            return;
+        }
+        data+=2;
+        vendor_length-=2;
+        length-=2;
+       ND_TCHECK2(*data, vendor_length);
+
+        ND_PRINT((ndo, "\n\t    Vendor Attribute: %u, Length: %u, Value: ",
+               vendor_type,
+               vendor_length));
+        for (idx = 0; idx < vendor_length ; idx++, data++)
+            ND_PRINT((ndo, "%c", (*data < 32 || *data > 126) ? '.' : *data));
+        length-=vendor_length;
+    }
+    return;
+
+   trunc:
+     ND_PRINT((ndo, "%s", tstr));
+}
 
 /******************************/
 /* Print an attribute numeric */
@@ -468,31 +618,31 @@ print_attr_string(register u_char *data, u_int length, u_short attr_code )
 /* Returns nothing.           */
 /******************************/
 static void
-print_attr_num(register u_char *data, u_int length, u_short attr_code )
+print_attr_num(netdissect_options *ndo,
+               register const u_char *data, u_int length, u_short attr_code)
 {
-   u_int8_t tag;
-   u_int32_t timeout;
-   
+   uint32_t timeout;
+
    if (length != 4)
    {
-       printf("{length %u != 4}", length);
+       ND_PRINT((ndo, "ERROR: length %u != 4", length));
        return;
    }
 
-   TCHECK2(data[0],4);
+   ND_TCHECK2(data[0],4);
                           /* This attribute has standard values */
-   if (attr_type[attr_code].siz_subtypes) 
+   if (attr_type[attr_code].siz_subtypes)
    {
       static const char **table;
-      u_int32_t data_value;
+      uint32_t data_value;
       table = attr_type[attr_code].subtypes;
-      
+
       if ( (attr_code == TUNNEL_TYPE) || (attr_code == TUNNEL_MEDIUM) )
       {
          if (!*data)
-            printf("{Tag[Unused]");
+            ND_PRINT((ndo, "Tag[Unused] "));
          else
-            printf("{Tag[%d]", *data);
+            ND_PRINT((ndo, "Tag[%d] ", *data));
          data++;
          data_value = EXTRACT_24BITS(data);
       }
@@ -500,11 +650,12 @@ print_attr_num(register u_char *data, u_int length, u_short attr_code )
       {
          data_value = EXTRACT_32BITS(data);
       }
-      if ( data_value <= (attr_type[attr_code].siz_subtypes - 1 +
-            attr_type[attr_code].first_subtype) )
-         printf("{%s}",table[data_value]);
+      if ( data_value <= (uint32_t)(attr_type[attr_code].siz_subtypes - 1 +
+            attr_type[attr_code].first_subtype) &&
+          data_value >= attr_type[attr_code].first_subtype )
+         ND_PRINT((ndo, "%s", table[data_value]));
       else
-         printf("{#%d}",data_value);          
+         ND_PRINT((ndo, "#%u", data_value));
    }
    else
    {
@@ -512,9 +663,9 @@ print_attr_num(register u_char *data, u_int length, u_short attr_code )
       {
         case FRM_IPX:
              if (EXTRACT_32BITS( data) == 0xFFFFFFFE )
-                printf("{NAS_select}");
+                ND_PRINT((ndo, "NAS Select"));
              else
-                printf("{%d}",EXTRACT_32BITS( data) );          
+                ND_PRINT((ndo, "%d", EXTRACT_32BITS(data)));
           break;
 
         case SESSION_TIMEOUT:
@@ -524,57 +675,64 @@ print_attr_num(register u_char *data, u_int length, u_short attr_code )
         case ACCT_INT_INTERVAL:
              timeout = EXTRACT_32BITS( data);
              if ( timeout < 60 )
-                printf( "{%02d secs}", timeout);
+                ND_PRINT((ndo,  "%02d secs", timeout));
              else
              {
                 if ( timeout < 3600 )
-                   printf( "{%02d:%02d min}", 
-                          timeout / 60, timeout % 60);
+                   ND_PRINT((ndo,  "%02d:%02d min",
+                          timeout / 60, timeout % 60));
                 else
-                   printf( "{%02d:%02d:%02d hours}",
-                          timeout / 3600, (timeout % 3600) / 60, 
-                          timeout % 60);
+                   ND_PRINT((ndo, "%02d:%02d:%02d hours",
+                          timeout / 3600, (timeout % 3600) / 60,
+                          timeout % 60));
              }
           break;
 
         case FRM_ATALK_LINK:
-             if (EXTRACT_32BITS(data) )          
-                printf("{%d}",EXTRACT_32BITS(data) );
+             if (EXTRACT_32BITS(data) )
+                ND_PRINT((ndo, "%d", EXTRACT_32BITS(data)));
              else
-                printf("{Unnumbered}" );
+                ND_PRINT((ndo, "Unnumbered"));
           break;
-             
+
         case FRM_ATALK_NETWORK:
-             if (EXTRACT_32BITS(data) )          
-                printf("{%d}",EXTRACT_32BITS(data) );
+             if (EXTRACT_32BITS(data) )
+                ND_PRINT((ndo, "%d", EXTRACT_32BITS(data)));
              else
-                printf("{NAS_assign}" );          
+                ND_PRINT((ndo, "NAS assigned"));
           break;
 
         case TUNNEL_PREFERENCE:
-            tag = *data;
-            data++;
-            if (tag == 0)
-               printf("{Tag[Unused] %d}",EXTRACT_24BITS(data) );
+            if (*data)
+               ND_PRINT((ndo, "Tag[%d] ", *data));
             else
-               printf("{Tag[%d] %d}", tag, EXTRACT_24BITS(data) );
+               ND_PRINT((ndo, "Tag[Unused] "));
+            data++;
+            ND_PRINT((ndo, "%d", EXTRACT_24BITS(data)));
+          break;
+
+        case EGRESS_VLAN_ID:
+            ND_PRINT((ndo, "%s (0x%02x) ",
+                   tok2str(rfc4675_tagged,"Unknown tag",*data),
+                   *data));
+            data++;
+            ND_PRINT((ndo, "%d", EXTRACT_24BITS(data)));
           break;
 
         default:
-             printf("{%d}",EXTRACT_32BITS( data) );
+             ND_PRINT((ndo, "%d", EXTRACT_32BITS(data)));
           break;
-      
+
       } /* switch */
-   
+
    } /* if-else */
 
    return;
-   
+
    trunc:
-     printf("|radius}");
+     ND_PRINT((ndo, "%s", tstr));
 }
 
-
 /*****************************/
 /* Print an attribute IPv4   */
 /* address value pointed by  */
@@ -583,41 +741,41 @@ print_attr_num(register u_char *data, u_int length, u_short attr_code )
 /* Returns nothing.          */
 /*****************************/
 static void
-print_attr_address(register u_char *data, u_int length, u_short attr_code )
+print_attr_address(netdissect_options *ndo,
+                   register const u_char *data, u_int length, u_short attr_code)
 {
    if (length != 4)
    {
-       printf("{length %u != 4}", length);
+       ND_PRINT((ndo, "ERROR: length %u != 4", length));
        return;
    }
 
-   TCHECK2(data[0],4);
-   
+   ND_TCHECK2(data[0],4);
+
    switch(attr_code)
    {
       case FRM_IPADDR:
       case LOG_IPHOST:
            if (EXTRACT_32BITS(data) == 0xFFFFFFFF )
-              printf("{User_select}");
+              ND_PRINT((ndo, "User Selected"));
            else
               if (EXTRACT_32BITS(data) == 0xFFFFFFFE )
-                 printf("{NAS_select}");
+                 ND_PRINT((ndo, "NAS Select"));
               else
-                 printf("{%s}",ipaddr_string(data));
+                 ND_PRINT((ndo, "%s",ipaddr_string(ndo, data)));
       break;
-      
+
       default:
-          printf("{%s}",ipaddr_string(data) );
+          ND_PRINT((ndo, "%s", ipaddr_string(ndo, data)));
       break;
    }
-   
+
    return;
-   
+
    trunc:
-     printf("{|radius}");
+     ND_PRINT((ndo, "%s", tstr));
 }
 
-
 /*************************************/
 /* Print an attribute of 'secs since */
 /* January 1, 1970 00:00 UTC' value  */
@@ -626,31 +784,32 @@ print_attr_address(register u_char *data, u_int length, u_short attr_code )
 /*************************************/
 /* Returns nothing.                  */
 /*************************************/
-static void print_attr_time(register u_char *data, u_int length, u_short attr_code)
+static void
+print_attr_time(netdissect_options *ndo,
+                register const u_char *data, u_int length, u_short attr_code _U_)
 {
    time_t attr_time;
    char string[26];
 
    if (length != 4)
    {
-       printf("{length %u != 4}", length);
+       ND_PRINT((ndo, "ERROR: length %u != 4", length));
        return;
    }
 
-   TCHECK2(data[0],4);
-   
+   ND_TCHECK2(data[0],4);
+
    attr_time = EXTRACT_32BITS(data);
    strlcpy(string, ctime(&attr_time), sizeof(string));
    /* Get rid of the newline */
    string[24] = '\0';
-   printf("{%.24s}", string);
+   ND_PRINT((ndo, "%.24s", string));
    return;
-   
+
    trunc:
-     printf("{|radius}");
+     ND_PRINT((ndo, "%s", tstr));
 }
 
-           
 /***********************************/
 /* Print an attribute of 'strange' */
 /* data format pointed by 'data'   */
@@ -658,201 +817,181 @@ static void print_attr_time(register u_char *data, u_int length, u_short attr_co
 /***********************************/
 /* Returns nothing.                */
 /***********************************/
-static void print_attr_strange(register u_char *data, u_int length, u_short attr_code)
+static void
+print_attr_strange(netdissect_options *ndo,
+                   register const u_char *data, u_int length, u_short attr_code)
 {
    u_short len_data;
-   
+
    switch(attr_code)
    {
       case ARAP_PASS:
            if (length != 16)
            {
-               printf("{length %u != 16}", length);
+               ND_PRINT((ndo, "ERROR: length %u != 16", length));
                return;
            }
-           printf("{User_challenge[");
-           TCHECK2(data[0],8);
+           ND_PRINT((ndo, "User_challenge ("));
+           ND_TCHECK2(data[0],8);
            len_data = 8;
            PRINT_HEX(len_data, data);
-           printf("] User_resp[");
-           TCHECK2(data[0],8);
+           ND_PRINT((ndo, ") User_resp("));
+           ND_TCHECK2(data[0],8);
            len_data = 8;
            PRINT_HEX(len_data, data);
-           printf("]}");
+           ND_PRINT((ndo, ")"));
         break;
-        
+
       case ARAP_FEATURES:
            if (length != 14)
            {
-               printf("{length %u != 14}", length);
+               ND_PRINT((ndo, "ERROR: length %u != 14", length));
                return;
            }
-           TCHECK2(data[0],1);
+           ND_TCHECK2(data[0],1);
            if (*data)
-              printf("{User_can_change_pass");
+              ND_PRINT((ndo, "User can change password"));
            else
-              printf("{User_cant_change_pass");
+              ND_PRINT((ndo, "User cannot change password"));
            data++;
-           TCHECK2(data[0],1);
-           printf(" Min_pass_len[%d]",*data);
+           ND_TCHECK2(data[0],1);
+           ND_PRINT((ndo, ", Min password length: %d", *data));
            data++;
-           printf(" Pass_created_at[");
-           TCHECK2(data[0],4);
+           ND_PRINT((ndo, ", created at: "));
+           ND_TCHECK2(data[0],4);
            len_data = 4;
            PRINT_HEX(len_data, data);
-           printf("] Pass_expired_in[");
-           TCHECK2(data[0],4);
+           ND_PRINT((ndo, ", expires in: "));
+           ND_TCHECK2(data[0],4);
            len_data = 4;
            PRINT_HEX(len_data, data);
-           printf("] Current_time[");
+           ND_PRINT((ndo, ", Current Time: "));
+           ND_TCHECK2(data[0],4);
            len_data = 4;
-           TCHECK2(data[0],4);
            PRINT_HEX(len_data, data);
-           printf("]}");
         break;
 
       case ARAP_CHALLENGE_RESP:
            if (length < 8)
            {
-               printf("{length %u != 8}", length);
+               ND_PRINT((ndo, "ERROR: length %u != 8", length));
                return;
            }
-           printf("{");
-           TCHECK2(data[0],8);
+           ND_TCHECK2(data[0],8);
            len_data = 8;
            PRINT_HEX(len_data, data);
-           printf("}");
         break;
    }
-   
+   return;
+
    trunc:
-     printf("|radius}");
+     ND_PRINT((ndo, "%s", tstr));
 }
 
-
-
 static void
-radius_attr_print(register const u_char *attr, u_int length)
+radius_attrs_print(netdissect_options *ndo,
+                   register const u_char *attr, u_int length)
 {
-   register const struct radius_attr *rad_attr = (struct radius_attr *)attr;
-   
-   if (length < 3)
-   {
-      printf(" [|radius]");
-      return;
-   }
-   printf(" Attr[ ");
+   register const struct radius_attr *rad_attr = (const struct radius_attr *)attr;
+   const char *attr_string;
+
    while (length > 0)
    {
-     if (rad_attr->len == 0)
+     if (length < 2)
+        goto trunc;
+     ND_TCHECK(*rad_attr);
+
+     if (rad_attr->type > 0 && rad_attr->type < TAM_SIZE(attr_type))
+       attr_string = attr_type[rad_attr->type].name;
+     else
+       attr_string = "Unknown";
+     if (rad_attr->len < 2)
      {
-       printf("(zero-length attribute)");
-       return;
+       ND_PRINT((ndo, "\n\t  %s Attribute (%u), length: %u (bogus, must be >= 2)",
+               attr_string,
+               rad_attr->type,
+               rad_attr->len));
+       return;
      }
-     if ( rad_attr->len <= length )
+     if (rad_attr->len > length)
      {
-        if ( !rad_attr->type || (rad_attr->type > (TAM_SIZE(attr_type)-1))  )
-           printf("#%d",rad_attr->type);
-        else
-        {
-           printf(" %s",attr_type[rad_attr->type].name);
-
-           if (rad_attr->len > 2)
-           {
-               if ( attr_type[rad_attr->type].print_func )
-                  (*attr_type[rad_attr->type].print_func)( 
-                                          ((u_char *)(rad_attr+1)),
-                                           rad_attr->len - 2, rad_attr->type);
-           }
-        }
+       ND_PRINT((ndo, "\n\t  %s Attribute (%u), length: %u (bogus, goes past end of packet)",
+               attr_string,
+               rad_attr->type,
+               rad_attr->len));
+        return;
      }
-     else
+     ND_PRINT((ndo, "\n\t  %s Attribute (%u), length: %u, Value: ",
+            attr_string,
+            rad_attr->type,
+            rad_attr->len));
+
+     if (rad_attr->type < TAM_SIZE(attr_type))
      {
-        printf(" [|radius]");
-        return;
+         if (rad_attr->len > 2)
+         {
+             if ( attr_type[rad_attr->type].print_func )
+                 (*attr_type[rad_attr->type].print_func)(
+                     ndo, ((const u_char *)(rad_attr+1)),
+                     rad_attr->len - 2, rad_attr->type);
+         }
      }
+     /* do we also want to see a hex dump ? */
+     if (ndo->ndo_vflag> 1)
+         print_unknown_data(ndo, (const u_char *)rad_attr+2, "\n\t    ", (rad_attr->len)-2);
+
      length-=(rad_attr->len);
-     rad_attr = (struct radius_attr *)( ((char *)(rad_attr))+rad_attr->len);
+     rad_attr = (const struct radius_attr *)( ((const char *)(rad_attr))+rad_attr->len);
    }
-   
-   printf(" ]");
-}
+   return;
 
+trunc:
+   ND_PRINT((ndo, "%s", tstr));
+}
 
 void
-radius_print(const u_char *dat, u_int length)
+radius_print(netdissect_options *ndo,
+             const u_char *dat, u_int length)
 {
    register const struct radius_hdr *rad;
-   register int i;
-   int len;
-   
-   i = min(length, snapend - dat);
+   u_int len, auth_idx;
 
-   if (i < MIN_RADIUS_LEN)
-   {
-         printf(" [|radius]");
-         return;
-   }
-
-   rad = (struct radius_hdr *)dat;
-   len = ntohs(rad->len);
+   ND_TCHECK2(*dat, MIN_RADIUS_LEN);
+   rad = (const struct radius_hdr *)dat;
+   len = EXTRACT_16BITS(&rad->len);
 
    if (len < MIN_RADIUS_LEN)
    {
-         printf(" [|radius]");
+         ND_PRINT((ndo, "%s", tstr));
          return;
    }
 
-   if (len < i)
-         i = len;
-   
-   i -= MIN_RADIUS_LEN;
-
-   switch (rad->code) 
-   {
-     case RADCMD_ACCESS_REQ:
-         printf(" rad-access-req %d", length);
-         break;
-
-     case RADCMD_ACCESS_ACC:
-         printf(" rad-access-accept %d", length);
-         break;
-
-     case RADCMD_ACCESS_REJ:
-         printf(" rad-access-reject %d", length);
-         break;
-
-     case RADCMD_ACCOUN_REQ:
-         printf(" rad-account-req %d", length);
-         break;
-
-     case RADCMD_ACCOUN_RES:
-         printf(" rad-account-resp %d", length);
-         break;
+   if (len > length)
+         len = length;
 
-     case RADCMD_ACCESS_CHA:
-         printf(" rad-access-cha %d", length);
-         break;
-
-     case RADCMD_STATUS_SER:
-         printf(" rad-status-serv %d", length);
-         break;
-
-     case RADCMD_STATUS_CLI:
-         printf(" rad-status-cli %d", length);
-         break;
+   if (ndo->ndo_vflag < 1) {
+       ND_PRINT((ndo, "RADIUS, %s (%u), id: 0x%02x length: %u",
+              tok2str(radius_command_values,"Unknown Command",rad->code),
+              rad->code,
+              rad->id,
+              len));
+       return;
+   }
+   else {
+       ND_PRINT((ndo, "RADIUS, length: %u\n\t%s (%u), id: 0x%02x, Authenticator: ",
+              len,
+              tok2str(radius_command_values,"Unknown Command",rad->code),
+              rad->code,
+              rad->id));
+
+       for(auth_idx=0; auth_idx < 16; auth_idx++)
+            ND_PRINT((ndo, "%02x", rad->auth[auth_idx]));
+   }
 
-     case RADCMD_RESERVED:
-         printf(" rad-reserved %d", length);
-         break;
+   if (len > MIN_RADIUS_LEN)
+      radius_attrs_print(ndo, dat + MIN_RADIUS_LEN, len - MIN_RADIUS_LEN);
+   return;
 
-     default:
-         printf(" rad-#%d %d", rad->code, length);
-         break;
-   }
-   printf(" [id %d]", rad->id);
-   if (i)
-      radius_attr_print( dat + MIN_RADIUS_LEN, i);  
+trunc:
+   ND_PRINT((ndo, "%s", tstr));
 }