Home | History | Annotate | Line # | Download | only in dist
print-radius.c revision 1.9
      1 /*
      2  * Copyright (C) 2000 Alfredo Andres Omella.  All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  *
      8  *   1. Redistributions of source code must retain the above copyright
      9  *      notice, this list of conditions and the following disclaimer.
     10  *   2. Redistributions in binary form must reproduce the above copyright
     11  *      notice, this list of conditions and the following disclaimer in
     12  *      the documentation and/or other materials provided with the
     13  *      distribution.
     14  *   3. The names of the authors may not be used to endorse or promote
     15  *      products derived from this software without specific prior
     16  *      written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
     19  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
     20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
     21  */
     22 
     23 /* \summary: Radius protocol printer */
     24 
     25 /*
     26  * Radius printer routines as specified on:
     27  *
     28  * RFC 2865:
     29  *      "Remote Authentication Dial In User Service (RADIUS)"
     30  *
     31  * RFC 2866:
     32  *      "RADIUS Accounting"
     33  *
     34  * RFC 2867:
     35  *      "RADIUS Accounting Modifications for Tunnel Protocol Support"
     36  *
     37  * RFC 2868:
     38  *      "RADIUS Attributes for Tunnel Protocol Support"
     39  *
     40  * RFC 2869:
     41  *      "RADIUS Extensions"
     42  *
     43  * RFC 3580:
     44  *      "IEEE 802.1X Remote Authentication Dial In User Service (RADIUS)"
     45  *      "Usage Guidelines"
     46  *
     47  * RFC 4675:
     48  *      "RADIUS Attributes for Virtual LAN and Priority Support"
     49  *
     50  * RFC 5176:
     51  *      "Dynamic Authorization Extensions to RADIUS"
     52  *
     53  * Alfredo Andres Omella (aandres (at) s21sec.com) v0.1 2000/09/15
     54  *
     55  * TODO: Among other things to print ok MacIntosh and Vendor values
     56  */
     57 
     58 #include <sys/cdefs.h>
     59 #ifndef lint
     60 __RCSID("$NetBSD: print-radius.c,v 1.9 2017/09/08 14:01:13 christos Exp $");
     61 #endif
     62 
     63 #ifdef HAVE_CONFIG_H
     64 #include "config.h"
     65 #endif
     66 
     67 #include <netdissect-stdinc.h>
     68 
     69 #include <string.h>
     70 
     71 #include "netdissect.h"
     72 #include "addrtoname.h"
     73 #include "extract.h"
     74 #include "oui.h"
     75 
     76 static const char tstr[] = " [|radius]";
     77 
     78 #define TAM_SIZE(x) (sizeof(x)/sizeof(x[0]) )
     79 
     80 #define PRINT_HEX(bytes_len, ptr_data)                               \
     81            while(bytes_len)                                          \
     82            {                                                         \
     83               ND_PRINT((ndo, "%02X", *ptr_data ));                   \
     84               ptr_data++;                                            \
     85               bytes_len--;                                           \
     86            }
     87 
     88 
     89 /* Radius packet codes */
     90 #define RADCMD_ACCESS_REQ   1 /* Access-Request      */
     91 #define RADCMD_ACCESS_ACC   2 /* Access-Accept       */
     92 #define RADCMD_ACCESS_REJ   3 /* Access-Reject       */
     93 #define RADCMD_ACCOUN_REQ   4 /* Accounting-Request  */
     94 #define RADCMD_ACCOUN_RES   5 /* Accounting-Response */
     95 #define RADCMD_ACCESS_CHA  11 /* Access-Challenge    */
     96 #define RADCMD_STATUS_SER  12 /* Status-Server       */
     97 #define RADCMD_STATUS_CLI  13 /* Status-Client       */
     98 #define RADCMD_DISCON_REQ  40 /* Disconnect-Request  */
     99 #define RADCMD_DISCON_ACK  41 /* Disconnect-ACK      */
    100 #define RADCMD_DISCON_NAK  42 /* Disconnect-NAK      */
    101 #define RADCMD_COA_REQ     43 /* CoA-Request         */
    102 #define RADCMD_COA_ACK     44 /* CoA-ACK             */
    103 #define RADCMD_COA_NAK     45 /* CoA-NAK             */
    104 #define RADCMD_RESERVED   255 /* Reserved            */
    105 
    106 static const struct tok radius_command_values[] = {
    107     { RADCMD_ACCESS_REQ, "Access-Request" },
    108     { RADCMD_ACCESS_ACC, "Access-Accept" },
    109     { RADCMD_ACCESS_REJ, "Access-Reject" },
    110     { RADCMD_ACCOUN_REQ, "Accounting-Request" },
    111     { RADCMD_ACCOUN_RES, "Accounting-Response" },
    112     { RADCMD_ACCESS_CHA, "Access-Challenge" },
    113     { RADCMD_STATUS_SER, "Status-Server" },
    114     { RADCMD_STATUS_CLI, "Status-Client" },
    115     { RADCMD_DISCON_REQ, "Disconnect-Request" },
    116     { RADCMD_DISCON_ACK, "Disconnect-ACK" },
    117     { RADCMD_DISCON_NAK, "Disconnect-NAK" },
    118     { RADCMD_COA_REQ,    "CoA-Request" },
    119     { RADCMD_COA_ACK,    "CoA-ACK" },
    120     { RADCMD_COA_NAK,    "CoA-NAK" },
    121     { RADCMD_RESERVED,   "Reserved" },
    122     { 0, NULL}
    123 };
    124 
    125 /********************************/
    126 /* Begin Radius Attribute types */
    127 /********************************/
    128 #define SERV_TYPE    6
    129 #define FRM_IPADDR   8
    130 #define LOG_IPHOST  14
    131 #define LOG_SERVICE 15
    132 #define FRM_IPX     23
    133 #define SESSION_TIMEOUT   27
    134 #define IDLE_TIMEOUT      28
    135 #define FRM_ATALK_LINK    37
    136 #define FRM_ATALK_NETWORK 38
    137 
    138 #define ACCT_DELAY        41
    139 #define ACCT_SESSION_TIME 46
    140 
    141 #define EGRESS_VLAN_ID   56
    142 #define EGRESS_VLAN_NAME 58
    143 
    144 #define TUNNEL_TYPE        64
    145 #define TUNNEL_MEDIUM      65
    146 #define TUNNEL_CLIENT_END  66
    147 #define TUNNEL_SERVER_END  67
    148 #define TUNNEL_PASS        69
    149 
    150 #define ARAP_PASS          70
    151 #define ARAP_FEATURES      71
    152 
    153 #define TUNNEL_PRIV_GROUP  81
    154 #define TUNNEL_ASSIGN_ID   82
    155 #define TUNNEL_PREFERENCE  83
    156 
    157 #define ARAP_CHALLENGE_RESP 84
    158 #define ACCT_INT_INTERVAL   85
    159 
    160 #define TUNNEL_CLIENT_AUTH 90
    161 #define TUNNEL_SERVER_AUTH 91
    162 /********************************/
    163 /* End Radius Attribute types */
    164 /********************************/
    165 
    166 #define RFC4675_TAGGED   0x31
    167 #define RFC4675_UNTAGGED 0x32
    168 
    169 static const struct tok rfc4675_tagged[] = {
    170     { RFC4675_TAGGED,   "Tagged" },
    171     { RFC4675_UNTAGGED, "Untagged" },
    172     { 0, NULL}
    173 };
    174 
    175 
    176 static void print_attr_string(netdissect_options *, register const u_char *, u_int, u_short );
    177 static void print_attr_num(netdissect_options *, register const u_char *, u_int, u_short );
    178 static void print_vendor_attr(netdissect_options *, register const u_char *, u_int, u_short );
    179 static void print_attr_address(netdissect_options *, register const u_char *, u_int, u_short);
    180 static void print_attr_time(netdissect_options *, register const u_char *, u_int, u_short);
    181 static void print_attr_strange(netdissect_options *, register const u_char *, u_int, u_short);
    182 
    183 
    184 struct radius_hdr { uint8_t  code; /* Radius packet code  */
    185                     uint8_t  id;   /* Radius packet id    */
    186                     uint16_t len;  /* Radius total length */
    187                     uint8_t  auth[16]; /* Authenticator   */
    188                   };
    189 
    190 #define MIN_RADIUS_LEN	20
    191 
    192 struct radius_attr { uint8_t type; /* Attribute type   */
    193                      uint8_t len;  /* Attribute length */
    194                    };
    195 
    196 
    197 /* Service-Type Attribute standard values */
    198 static const char *serv_type[]={ NULL,
    199                                 "Login",
    200                                 "Framed",
    201                                 "Callback Login",
    202                                 "Callback Framed",
    203                                 "Outbound",
    204                                 "Administrative",
    205                                 "NAS Prompt",
    206                                 "Authenticate Only",
    207                                 "Callback NAS Prompt",
    208                                 "Call Check",
    209                                 "Callback Administrative",
    210                                };
    211 
    212 /* Framed-Protocol Attribute standard values */
    213 static const char *frm_proto[]={ NULL,
    214                                  "PPP",
    215                                  "SLIP",
    216                                  "ARAP",
    217                                  "Gandalf proprietary",
    218                                  "Xylogics IPX/SLIP",
    219                                  "X.75 Synchronous",
    220                                };
    221 
    222 /* Framed-Routing Attribute standard values */
    223 static const char *frm_routing[]={ "None",
    224                                    "Send",
    225                                    "Listen",
    226                                    "Send&Listen",
    227                                  };
    228 
    229 /* Framed-Compression Attribute standard values */
    230 static const char *frm_comp[]={ "None",
    231                                 "VJ TCP/IP",
    232                                 "IPX",
    233                                 "Stac-LZS",
    234                               };
    235 
    236 /* Login-Service Attribute standard values */
    237 static const char *login_serv[]={ "Telnet",
    238                                   "Rlogin",
    239                                   "TCP Clear",
    240                                   "PortMaster(proprietary)",
    241                                   "LAT",
    242                                   "X.25-PAD",
    243                                   "X.25-T3POS",
    244                                   "Unassigned",
    245                                   "TCP Clear Quiet",
    246                                 };
    247 
    248 
    249 /* Termination-Action Attribute standard values */
    250 static const char *term_action[]={ "Default",
    251                                    "RADIUS-Request",
    252                                  };
    253 
    254 /* Ingress-Filters Attribute standard values */
    255 static const char *ingress_filters[]={ NULL,
    256                                        "Enabled",
    257                                        "Disabled",
    258                                      };
    259 
    260 /* NAS-Port-Type Attribute standard values */
    261 static const char *nas_port_type[]={ "Async",
    262                                      "Sync",
    263                                      "ISDN Sync",
    264                                      "ISDN Async V.120",
    265                                      "ISDN Async V.110",
    266                                      "Virtual",
    267                                      "PIAFS",
    268                                      "HDLC Clear Channel",
    269                                      "X.25",
    270                                      "X.75",
    271                                      "G.3 Fax",
    272                                      "SDSL",
    273                                      "ADSL-CAP",
    274                                      "ADSL-DMT",
    275                                      "ISDN-DSL",
    276                                      "Ethernet",
    277                                      "xDSL",
    278                                      "Cable",
    279                                      "Wireless - Other",
    280                                      "Wireless - IEEE 802.11",
    281                                    };
    282 
    283 /* Acct-Status-Type Accounting Attribute standard values */
    284 static const char *acct_status[]={ NULL,
    285                                    "Start",
    286                                    "Stop",
    287                                    "Interim-Update",
    288                                    "Unassigned",
    289                                    "Unassigned",
    290                                    "Unassigned",
    291                                    "Accounting-On",
    292                                    "Accounting-Off",
    293                                    "Tunnel-Start",
    294                                    "Tunnel-Stop",
    295                                    "Tunnel-Reject",
    296                                    "Tunnel-Link-Start",
    297                                    "Tunnel-Link-Stop",
    298                                    "Tunnel-Link-Reject",
    299                                    "Failed",
    300                                  };
    301 
    302 /* Acct-Authentic Accounting Attribute standard values */
    303 static const char *acct_auth[]={ NULL,
    304                                  "RADIUS",
    305                                  "Local",
    306                                  "Remote",
    307                                };
    308 
    309 /* Acct-Terminate-Cause Accounting Attribute standard values */
    310 static const char *acct_term[]={ NULL,
    311                                  "User Request",
    312                                  "Lost Carrier",
    313                                  "Lost Service",
    314                                  "Idle Timeout",
    315                                  "Session Timeout",
    316                                  "Admin Reset",
    317                                  "Admin Reboot",
    318                                  "Port Error",
    319                                  "NAS Error",
    320                                  "NAS Request",
    321                                  "NAS Reboot",
    322                                  "Port Unneeded",
    323                                  "Port Preempted",
    324                                  "Port Suspended",
    325                                  "Service Unavailable",
    326                                  "Callback",
    327                                  "User Error",
    328                                  "Host Request",
    329                                };
    330 
    331 /* Tunnel-Type Attribute standard values */
    332 static const char *tunnel_type[]={ NULL,
    333                                    "PPTP",
    334                                    "L2F",
    335                                    "L2TP",
    336                                    "ATMP",
    337                                    "VTP",
    338                                    "AH",
    339                                    "IP-IP",
    340                                    "MIN-IP-IP",
    341                                    "ESP",
    342                                    "GRE",
    343                                    "DVS",
    344                                    "IP-in-IP Tunneling",
    345                                    "VLAN",
    346                                  };
    347 
    348 /* Tunnel-Medium-Type Attribute standard values */
    349 static const char *tunnel_medium[]={ NULL,
    350                                      "IPv4",
    351                                      "IPv6",
    352                                      "NSAP",
    353                                      "HDLC",
    354                                      "BBN 1822",
    355                                      "802",
    356                                      "E.163",
    357                                      "E.164",
    358                                      "F.69",
    359                                      "X.121",
    360                                      "IPX",
    361                                      "Appletalk",
    362                                      "Decnet IV",
    363                                      "Banyan Vines",
    364                                      "E.164 with NSAP subaddress",
    365                                    };
    366 
    367 /* ARAP-Zone-Access Attribute standard values */
    368 static const char *arap_zone[]={ NULL,
    369                                  "Only access to dfl zone",
    370                                  "Use zone filter inc.",
    371                                  "Not used",
    372                                  "Use zone filter exc.",
    373                                };
    374 
    375 static const char *prompt[]={ "No Echo",
    376                               "Echo",
    377                             };
    378 
    379 
    380 static struct attrtype {
    381                   const char *name;      /* Attribute name                 */
    382                   const char **subtypes; /* Standard Values (if any)       */
    383                   u_char siz_subtypes;   /* Size of total standard values  */
    384                   u_char first_subtype;  /* First standard value is 0 or 1 */
    385                   void (*print_func)(netdissect_options *, register const u_char *, u_int, u_short);
    386                 } attr_type[]=
    387   {
    388      { NULL,                              NULL, 0, 0, NULL               },
    389      { "User-Name",                       NULL, 0, 0, print_attr_string  },
    390      { "User-Password",                   NULL, 0, 0, NULL               },
    391      { "CHAP-Password",                   NULL, 0, 0, NULL               },
    392      { "NAS-IP-Address",                  NULL, 0, 0, print_attr_address },
    393      { "NAS-Port",                        NULL, 0, 0, print_attr_num     },
    394      { "Service-Type",                    serv_type, TAM_SIZE(serv_type)-1, 1, print_attr_num },
    395      { "Framed-Protocol",                 frm_proto, TAM_SIZE(frm_proto)-1, 1, print_attr_num },
    396      { "Framed-IP-Address",               NULL, 0, 0, print_attr_address },
    397      { "Framed-IP-Netmask",               NULL, 0, 0, print_attr_address },
    398      { "Framed-Routing",                  frm_routing, TAM_SIZE(frm_routing), 0, print_attr_num },
    399      { "Filter-Id",                       NULL, 0, 0, print_attr_string  },
    400      { "Framed-MTU",                      NULL, 0, 0, print_attr_num     },
    401      { "Framed-Compression",              frm_comp, TAM_SIZE(frm_comp),   0, print_attr_num },
    402      { "Login-IP-Host",                   NULL, 0, 0, print_attr_address },
    403      { "Login-Service",                   login_serv, TAM_SIZE(login_serv), 0, print_attr_num },
    404      { "Login-TCP-Port",                  NULL, 0, 0, print_attr_num     },
    405      { "Unassigned",                      NULL, 0, 0, NULL }, /*17*/
    406      { "Reply-Message",                   NULL, 0, 0, print_attr_string },
    407      { "Callback-Number",                 NULL, 0, 0, print_attr_string },
    408      { "Callback-Id",                     NULL, 0, 0, print_attr_string },
    409      { "Unassigned",                      NULL, 0, 0, NULL }, /*21*/
    410      { "Framed-Route",                    NULL, 0, 0, print_attr_string },
    411      { "Framed-IPX-Network",              NULL, 0, 0, print_attr_num    },
    412      { "State",                           NULL, 0, 0, print_attr_string },
    413      { "Class",                           NULL, 0, 0, print_attr_string },
    414      { "Vendor-Specific",                 NULL, 0, 0, print_vendor_attr },
    415      { "Session-Timeout",                 NULL, 0, 0, print_attr_num    },
    416      { "Idle-Timeout",                    NULL, 0, 0, print_attr_num    },
    417      { "Termination-Action",              term_action, TAM_SIZE(term_action), 0, print_attr_num },
    418      { "Called-Station-Id",               NULL, 0, 0, print_attr_string },
    419      { "Calling-Station-Id",              NULL, 0, 0, print_attr_string },
    420      { "NAS-Identifier",                  NULL, 0, 0, print_attr_string },
    421      { "Proxy-State",                     NULL, 0, 0, print_attr_string },
    422      { "Login-LAT-Service",               NULL, 0, 0, print_attr_string },
    423      { "Login-LAT-Node",                  NULL, 0, 0, print_attr_string },
    424      { "Login-LAT-Group",                 NULL, 0, 0, print_attr_string },
    425      { "Framed-AppleTalk-Link",           NULL, 0, 0, print_attr_num    },
    426      { "Framed-AppleTalk-Network",        NULL, 0, 0, print_attr_num    },
    427      { "Framed-AppleTalk-Zone",           NULL, 0, 0, print_attr_string },
    428      { "Acct-Status-Type",                acct_status, TAM_SIZE(acct_status)-1, 1, print_attr_num },
    429      { "Acct-Delay-Time",                 NULL, 0, 0, print_attr_num    },
    430      { "Acct-Input-Octets",               NULL, 0, 0, print_attr_num    },
    431      { "Acct-Output-Octets",              NULL, 0, 0, print_attr_num    },
    432      { "Acct-Session-Id",                 NULL, 0, 0, print_attr_string },
    433      { "Acct-Authentic",                  acct_auth, TAM_SIZE(acct_auth)-1, 1, print_attr_num },
    434      { "Acct-Session-Time",               NULL, 0, 0, print_attr_num },
    435      { "Acct-Input-Packets",              NULL, 0, 0, print_attr_num },
    436      { "Acct-Output-Packets",             NULL, 0, 0, print_attr_num },
    437      { "Acct-Terminate-Cause",            acct_term, TAM_SIZE(acct_term)-1, 1, print_attr_num },
    438      { "Acct-Multi-Session-Id",           NULL, 0, 0, print_attr_string },
    439      { "Acct-Link-Count",                 NULL, 0, 0, print_attr_num },
    440      { "Acct-Input-Gigawords",            NULL, 0, 0, print_attr_num },
    441      { "Acct-Output-Gigawords",           NULL, 0, 0, print_attr_num },
    442      { "Unassigned",                      NULL, 0, 0, NULL }, /*54*/
    443      { "Event-Timestamp",                 NULL, 0, 0, print_attr_time },
    444      { "Egress-VLANID",                   NULL, 0, 0, print_attr_num },
    445      { "Ingress-Filters",                 ingress_filters, TAM_SIZE(ingress_filters)-1, 1, print_attr_num },
    446      { "Egress-VLAN-Name",                NULL, 0, 0, print_attr_string },
    447      { "User-Priority-Table",             NULL, 0, 0, NULL },
    448      { "CHAP-Challenge",                  NULL, 0, 0, print_attr_string },
    449      { "NAS-Port-Type",                   nas_port_type, TAM_SIZE(nas_port_type), 0, print_attr_num },
    450      { "Port-Limit",                      NULL, 0, 0, print_attr_num },
    451      { "Login-LAT-Port",                  NULL, 0, 0, print_attr_string }, /*63*/
    452      { "Tunnel-Type",                     tunnel_type, TAM_SIZE(tunnel_type)-1, 1, print_attr_num },
    453      { "Tunnel-Medium-Type",              tunnel_medium, TAM_SIZE(tunnel_medium)-1, 1, print_attr_num },
    454      { "Tunnel-Client-Endpoint",          NULL, 0, 0, print_attr_string },
    455      { "Tunnel-Server-Endpoint",          NULL, 0, 0, print_attr_string },
    456      { "Acct-Tunnel-Connection",          NULL, 0, 0, print_attr_string },
    457      { "Tunnel-Password",                 NULL, 0, 0, print_attr_string  },
    458      { "ARAP-Password",                   NULL, 0, 0, print_attr_strange },
    459      { "ARAP-Features",                   NULL, 0, 0, print_attr_strange },
    460      { "ARAP-Zone-Access",                arap_zone, TAM_SIZE(arap_zone)-1, 1, print_attr_num }, /*72*/
    461      { "ARAP-Security",                   NULL, 0, 0, print_attr_string },
    462      { "ARAP-Security-Data",              NULL, 0, 0, print_attr_string },
    463      { "Password-Retry",                  NULL, 0, 0, print_attr_num    },
    464      { "Prompt",                          prompt, TAM_SIZE(prompt), 0, print_attr_num },
    465      { "Connect-Info",                    NULL, 0, 0, print_attr_string   },
    466      { "Configuration-Token",             NULL, 0, 0, print_attr_string   },
    467      { "EAP-Message",                     NULL, 0, 0, print_attr_string   },
    468      { "Message-Authenticator",           NULL, 0, 0, print_attr_string }, /*80*/
    469      { "Tunnel-Private-Group-ID",         NULL, 0, 0, print_attr_string },
    470      { "Tunnel-Assignment-ID",            NULL, 0, 0, print_attr_string },
    471      { "Tunnel-Preference",               NULL, 0, 0, print_attr_num    },
    472      { "ARAP-Challenge-Response",         NULL, 0, 0, print_attr_strange },
    473      { "Acct-Interim-Interval",           NULL, 0, 0, print_attr_num     },
    474      { "Acct-Tunnel-Packets-Lost",        NULL, 0, 0, print_attr_num }, /*86*/
    475      { "NAS-Port-Id",                     NULL, 0, 0, print_attr_string },
    476      { "Framed-Pool",                     NULL, 0, 0, print_attr_string },
    477      { "CUI",                             NULL, 0, 0, print_attr_string },
    478      { "Tunnel-Client-Auth-ID",           NULL, 0, 0, print_attr_string },
    479      { "Tunnel-Server-Auth-ID",           NULL, 0, 0, print_attr_string },
    480      { "Unassigned",                      NULL, 0, 0, NULL }, /*92*/
    481      { "Unassigned",                      NULL, 0, 0, NULL }  /*93*/
    482   };
    483 
    484 
    485 /*****************************/
    486 /* Print an attribute string */
    487 /* value pointed by 'data'   */
    488 /* and 'length' size.        */
    489 /*****************************/
    490 /* Returns nothing.          */
    491 /*****************************/
    492 static void
    493 print_attr_string(netdissect_options *ndo,
    494                   register const u_char *data, u_int length, u_short attr_code)
    495 {
    496    register u_int i;
    497 
    498    ND_TCHECK2(data[0],length);
    499 
    500    switch(attr_code)
    501    {
    502       case TUNNEL_PASS:
    503            if (length < 3)
    504               goto trunc;
    505            if (*data && (*data <=0x1F) )
    506               ND_PRINT((ndo, "Tag[%u] ", *data));
    507            else
    508               ND_PRINT((ndo, "Tag[Unused] "));
    509            data++;
    510            length--;
    511            ND_PRINT((ndo, "Salt %u ", EXTRACT_16BITS(data)));
    512            data+=2;
    513            length-=2;
    514         break;
    515       case TUNNEL_CLIENT_END:
    516       case TUNNEL_SERVER_END:
    517       case TUNNEL_PRIV_GROUP:
    518       case TUNNEL_ASSIGN_ID:
    519       case TUNNEL_CLIENT_AUTH:
    520       case TUNNEL_SERVER_AUTH:
    521            if (*data <= 0x1F)
    522            {
    523               if (length < 1)
    524                  goto trunc;
    525               if (*data)
    526                 ND_PRINT((ndo, "Tag[%u] ", *data));
    527               else
    528                 ND_PRINT((ndo, "Tag[Unused] "));
    529               data++;
    530               length--;
    531            }
    532         break;
    533       case EGRESS_VLAN_NAME:
    534            if (length < 1)
    535               goto trunc;
    536            ND_PRINT((ndo, "%s (0x%02x) ",
    537                   tok2str(rfc4675_tagged,"Unknown tag",*data),
    538                   *data));
    539            data++;
    540            length--;
    541         break;
    542    }
    543 
    544    for (i=0; i < length && *data; i++, data++)
    545        ND_PRINT((ndo, "%c", (*data < 32 || *data > 126) ? '.' : *data));
    546 
    547    return;
    548 
    549    trunc:
    550       ND_PRINT((ndo, "%s", tstr));
    551 }
    552 
    553 /*
    554  * print vendor specific attributes
    555  */
    556 static void
    557 print_vendor_attr(netdissect_options *ndo,
    558                   register const u_char *data, u_int length, u_short attr_code _U_)
    559 {
    560     u_int idx;
    561     u_int vendor_id;
    562     u_int vendor_type;
    563     u_int vendor_length;
    564 
    565     if (length < 4)
    566         goto trunc;
    567     ND_TCHECK2(*data, 4);
    568     vendor_id = EXTRACT_32BITS(data);
    569     data+=4;
    570     length-=4;
    571 
    572     ND_PRINT((ndo, "Vendor: %s (%u)",
    573            tok2str(smi_values,"Unknown",vendor_id),
    574            vendor_id));
    575 
    576     while (length >= 2) {
    577 	ND_TCHECK2(*data, 2);
    578 
    579         vendor_type = *(data);
    580         vendor_length = *(data+1);
    581 
    582         if (vendor_length < 2)
    583         {
    584             ND_PRINT((ndo, "\n\t    Vendor Attribute: %u, Length: %u (bogus, must be >= 2)",
    585                    vendor_type,
    586                    vendor_length));
    587             return;
    588         }
    589         if (vendor_length > length)
    590         {
    591             ND_PRINT((ndo, "\n\t    Vendor Attribute: %u, Length: %u (bogus, goes past end of vendor-specific attribute)",
    592                    vendor_type,
    593                    vendor_length));
    594             return;
    595         }
    596         data+=2;
    597         vendor_length-=2;
    598         length-=2;
    599 	ND_TCHECK2(*data, vendor_length);
    600 
    601         ND_PRINT((ndo, "\n\t    Vendor Attribute: %u, Length: %u, Value: ",
    602                vendor_type,
    603                vendor_length));
    604         for (idx = 0; idx < vendor_length ; idx++, data++)
    605             ND_PRINT((ndo, "%c", (*data < 32 || *data > 126) ? '.' : *data));
    606         length-=vendor_length;
    607     }
    608     return;
    609 
    610    trunc:
    611      ND_PRINT((ndo, "%s", tstr));
    612 }
    613 
    614 /******************************/
    615 /* Print an attribute numeric */
    616 /* value pointed by 'data'    */
    617 /* and 'length' size.         */
    618 /******************************/
    619 /* Returns nothing.           */
    620 /******************************/
    621 static void
    622 print_attr_num(netdissect_options *ndo,
    623                register const u_char *data, u_int length, u_short attr_code)
    624 {
    625    uint32_t timeout;
    626 
    627    if (length != 4)
    628    {
    629        ND_PRINT((ndo, "ERROR: length %u != 4", length));
    630        return;
    631    }
    632 
    633    ND_TCHECK2(data[0],4);
    634                           /* This attribute has standard values */
    635    if (attr_type[attr_code].siz_subtypes)
    636    {
    637       static const char **table;
    638       uint32_t data_value;
    639       table = attr_type[attr_code].subtypes;
    640 
    641       if ( (attr_code == TUNNEL_TYPE) || (attr_code == TUNNEL_MEDIUM) )
    642       {
    643          if (!*data)
    644             ND_PRINT((ndo, "Tag[Unused] "));
    645          else
    646             ND_PRINT((ndo, "Tag[%d] ", *data));
    647          data++;
    648          data_value = EXTRACT_24BITS(data);
    649       }
    650       else
    651       {
    652          data_value = EXTRACT_32BITS(data);
    653       }
    654       if ( data_value <= (uint32_t)(attr_type[attr_code].siz_subtypes - 1 +
    655             attr_type[attr_code].first_subtype) &&
    656 	   data_value >= attr_type[attr_code].first_subtype )
    657          ND_PRINT((ndo, "%s", table[data_value]));
    658       else
    659          ND_PRINT((ndo, "#%u", data_value));
    660    }
    661    else
    662    {
    663       switch(attr_code) /* Be aware of special cases... */
    664       {
    665         case FRM_IPX:
    666              if (EXTRACT_32BITS( data) == 0xFFFFFFFE )
    667                 ND_PRINT((ndo, "NAS Select"));
    668              else
    669                 ND_PRINT((ndo, "%d", EXTRACT_32BITS(data)));
    670           break;
    671 
    672         case SESSION_TIMEOUT:
    673         case IDLE_TIMEOUT:
    674         case ACCT_DELAY:
    675         case ACCT_SESSION_TIME:
    676         case ACCT_INT_INTERVAL:
    677              timeout = EXTRACT_32BITS( data);
    678              if ( timeout < 60 )
    679                 ND_PRINT((ndo,  "%02d secs", timeout));
    680              else
    681              {
    682                 if ( timeout < 3600 )
    683                    ND_PRINT((ndo,  "%02d:%02d min",
    684                           timeout / 60, timeout % 60));
    685                 else
    686                    ND_PRINT((ndo, "%02d:%02d:%02d hours",
    687                           timeout / 3600, (timeout % 3600) / 60,
    688                           timeout % 60));
    689              }
    690           break;
    691 
    692         case FRM_ATALK_LINK:
    693              if (EXTRACT_32BITS(data) )
    694                 ND_PRINT((ndo, "%d", EXTRACT_32BITS(data)));
    695              else
    696                 ND_PRINT((ndo, "Unnumbered"));
    697           break;
    698 
    699         case FRM_ATALK_NETWORK:
    700              if (EXTRACT_32BITS(data) )
    701                 ND_PRINT((ndo, "%d", EXTRACT_32BITS(data)));
    702              else
    703                 ND_PRINT((ndo, "NAS assigned"));
    704           break;
    705 
    706         case TUNNEL_PREFERENCE:
    707             if (*data)
    708                ND_PRINT((ndo, "Tag[%d] ", *data));
    709             else
    710                ND_PRINT((ndo, "Tag[Unused] "));
    711             data++;
    712             ND_PRINT((ndo, "%d", EXTRACT_24BITS(data)));
    713           break;
    714 
    715         case EGRESS_VLAN_ID:
    716             ND_PRINT((ndo, "%s (0x%02x) ",
    717                    tok2str(rfc4675_tagged,"Unknown tag",*data),
    718                    *data));
    719             data++;
    720             ND_PRINT((ndo, "%d", EXTRACT_24BITS(data)));
    721           break;
    722 
    723         default:
    724              ND_PRINT((ndo, "%d", EXTRACT_32BITS(data)));
    725           break;
    726 
    727       } /* switch */
    728 
    729    } /* if-else */
    730 
    731    return;
    732 
    733    trunc:
    734      ND_PRINT((ndo, "%s", tstr));
    735 }
    736 
    737 /*****************************/
    738 /* Print an attribute IPv4   */
    739 /* address value pointed by  */
    740 /* 'data' and 'length' size. */
    741 /*****************************/
    742 /* Returns nothing.          */
    743 /*****************************/
    744 static void
    745 print_attr_address(netdissect_options *ndo,
    746                    register const u_char *data, u_int length, u_short attr_code)
    747 {
    748    if (length != 4)
    749    {
    750        ND_PRINT((ndo, "ERROR: length %u != 4", length));
    751        return;
    752    }
    753 
    754    ND_TCHECK2(data[0],4);
    755 
    756    switch(attr_code)
    757    {
    758       case FRM_IPADDR:
    759       case LOG_IPHOST:
    760            if (EXTRACT_32BITS(data) == 0xFFFFFFFF )
    761               ND_PRINT((ndo, "User Selected"));
    762            else
    763               if (EXTRACT_32BITS(data) == 0xFFFFFFFE )
    764                  ND_PRINT((ndo, "NAS Select"));
    765               else
    766                  ND_PRINT((ndo, "%s",ipaddr_string(ndo, data)));
    767       break;
    768 
    769       default:
    770           ND_PRINT((ndo, "%s", ipaddr_string(ndo, data)));
    771       break;
    772    }
    773 
    774    return;
    775 
    776    trunc:
    777      ND_PRINT((ndo, "%s", tstr));
    778 }
    779 
    780 /*************************************/
    781 /* Print an attribute of 'secs since */
    782 /* January 1, 1970 00:00 UTC' value  */
    783 /* pointed by 'data' and 'length'    */
    784 /* size.                             */
    785 /*************************************/
    786 /* Returns nothing.                  */
    787 /*************************************/
    788 static void
    789 print_attr_time(netdissect_options *ndo,
    790                 register const u_char *data, u_int length, u_short attr_code _U_)
    791 {
    792    time_t attr_time;
    793    char string[26];
    794    const char *p;
    795 
    796    if (length != 4)
    797    {
    798        ND_PRINT((ndo, "ERROR: length %u != 4", length));
    799        return;
    800    }
    801 
    802    ND_TCHECK2(data[0],4);
    803 
    804    attr_time = EXTRACT_32BITS(data);
    805    if ((p = ctime(&attr_time)) == NULL)
    806 	p = "?";
    807    strlcpy(string, p, sizeof(string));
    808    /* Get rid of the newline */
    809    string[24] = '\0';
    810    ND_PRINT((ndo, "%.24s", string));
    811    return;
    812 
    813    trunc:
    814      ND_PRINT((ndo, "%s", tstr));
    815 }
    816 
    817 /***********************************/
    818 /* Print an attribute of 'strange' */
    819 /* data format pointed by 'data'   */
    820 /* and 'length' size.              */
    821 /***********************************/
    822 /* Returns nothing.                */
    823 /***********************************/
    824 static void
    825 print_attr_strange(netdissect_options *ndo,
    826                    register const u_char *data, u_int length, u_short attr_code)
    827 {
    828    u_short len_data;
    829 
    830    switch(attr_code)
    831    {
    832       case ARAP_PASS:
    833            if (length != 16)
    834            {
    835                ND_PRINT((ndo, "ERROR: length %u != 16", length));
    836                return;
    837            }
    838            ND_PRINT((ndo, "User_challenge ("));
    839            ND_TCHECK2(data[0],8);
    840            len_data = 8;
    841            PRINT_HEX(len_data, data);
    842            ND_PRINT((ndo, ") User_resp("));
    843            ND_TCHECK2(data[0],8);
    844            len_data = 8;
    845            PRINT_HEX(len_data, data);
    846            ND_PRINT((ndo, ")"));
    847         break;
    848 
    849       case ARAP_FEATURES:
    850            if (length != 14)
    851            {
    852                ND_PRINT((ndo, "ERROR: length %u != 14", length));
    853                return;
    854            }
    855            ND_TCHECK2(data[0],1);
    856            if (*data)
    857               ND_PRINT((ndo, "User can change password"));
    858            else
    859               ND_PRINT((ndo, "User cannot change password"));
    860            data++;
    861            ND_TCHECK2(data[0],1);
    862            ND_PRINT((ndo, ", Min password length: %d", *data));
    863            data++;
    864            ND_PRINT((ndo, ", created at: "));
    865            ND_TCHECK2(data[0],4);
    866            len_data = 4;
    867            PRINT_HEX(len_data, data);
    868            ND_PRINT((ndo, ", expires in: "));
    869            ND_TCHECK2(data[0],4);
    870            len_data = 4;
    871            PRINT_HEX(len_data, data);
    872            ND_PRINT((ndo, ", Current Time: "));
    873            ND_TCHECK2(data[0],4);
    874            len_data = 4;
    875            PRINT_HEX(len_data, data);
    876         break;
    877 
    878       case ARAP_CHALLENGE_RESP:
    879            if (length < 8)
    880            {
    881                ND_PRINT((ndo, "ERROR: length %u != 8", length));
    882                return;
    883            }
    884            ND_TCHECK2(data[0],8);
    885            len_data = 8;
    886            PRINT_HEX(len_data, data);
    887         break;
    888    }
    889    return;
    890 
    891    trunc:
    892      ND_PRINT((ndo, "%s", tstr));
    893 }
    894 
    895 static void
    896 radius_attrs_print(netdissect_options *ndo,
    897                    register const u_char *attr, u_int length)
    898 {
    899    register const struct radius_attr *rad_attr = (const struct radius_attr *)attr;
    900    const char *attr_string;
    901 
    902    while (length > 0)
    903    {
    904      if (length < 2)
    905         goto trunc;
    906      ND_TCHECK(*rad_attr);
    907 
    908      if (rad_attr->type > 0 && rad_attr->type < TAM_SIZE(attr_type))
    909 	attr_string = attr_type[rad_attr->type].name;
    910      else
    911 	attr_string = "Unknown";
    912      if (rad_attr->len < 2)
    913      {
    914 	ND_PRINT((ndo, "\n\t  %s Attribute (%u), length: %u (bogus, must be >= 2)",
    915                attr_string,
    916                rad_attr->type,
    917                rad_attr->len));
    918 	return;
    919      }
    920      if (rad_attr->len > length)
    921      {
    922 	ND_PRINT((ndo, "\n\t  %s Attribute (%u), length: %u (bogus, goes past end of packet)",
    923                attr_string,
    924                rad_attr->type,
    925                rad_attr->len));
    926         return;
    927      }
    928      ND_PRINT((ndo, "\n\t  %s Attribute (%u), length: %u, Value: ",
    929             attr_string,
    930             rad_attr->type,
    931             rad_attr->len));
    932 
    933      if (rad_attr->type < TAM_SIZE(attr_type))
    934      {
    935          if (rad_attr->len > 2)
    936          {
    937              if ( attr_type[rad_attr->type].print_func )
    938                  (*attr_type[rad_attr->type].print_func)(
    939                      ndo, ((const u_char *)(rad_attr+1)),
    940                      rad_attr->len - 2, rad_attr->type);
    941          }
    942      }
    943      /* do we also want to see a hex dump ? */
    944      if (ndo->ndo_vflag> 1)
    945          print_unknown_data(ndo, (const u_char *)rad_attr+2, "\n\t    ", (rad_attr->len)-2);
    946 
    947      length-=(rad_attr->len);
    948      rad_attr = (const struct radius_attr *)( ((const char *)(rad_attr))+rad_attr->len);
    949    }
    950    return;
    951 
    952 trunc:
    953    ND_PRINT((ndo, "%s", tstr));
    954 }
    955 
    956 void
    957 radius_print(netdissect_options *ndo,
    958              const u_char *dat, u_int length)
    959 {
    960    register const struct radius_hdr *rad;
    961    u_int len, auth_idx;
    962 
    963    ND_TCHECK2(*dat, MIN_RADIUS_LEN);
    964    rad = (const struct radius_hdr *)dat;
    965    len = EXTRACT_16BITS(&rad->len);
    966 
    967    if (len < MIN_RADIUS_LEN)
    968    {
    969 	  ND_PRINT((ndo, "%s", tstr));
    970 	  return;
    971    }
    972 
    973    if (len > length)
    974 	  len = length;
    975 
    976    if (ndo->ndo_vflag < 1) {
    977        ND_PRINT((ndo, "RADIUS, %s (%u), id: 0x%02x length: %u",
    978               tok2str(radius_command_values,"Unknown Command",rad->code),
    979               rad->code,
    980               rad->id,
    981               len));
    982        return;
    983    }
    984    else {
    985        ND_PRINT((ndo, "RADIUS, length: %u\n\t%s (%u), id: 0x%02x, Authenticator: ",
    986               len,
    987               tok2str(radius_command_values,"Unknown Command",rad->code),
    988               rad->code,
    989               rad->id));
    990 
    991        for(auth_idx=0; auth_idx < 16; auth_idx++)
    992             ND_PRINT((ndo, "%02x", rad->auth[auth_idx]));
    993    }
    994 
    995    if (len > MIN_RADIUS_LEN)
    996       radius_attrs_print(ndo, dat + MIN_RADIUS_LEN, len - MIN_RADIUS_LEN);
    997    return;
    998 
    999 trunc:
   1000    ND_PRINT((ndo, "%s", tstr));
   1001 }
   1002