Home | History | Annotate | Line # | Download | only in dist
print-radius.c revision 1.7
      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  * Radius printer routines as specified on:
     24  *
     25  * RFC 2865:
     26  *      "Remote Authentication Dial In User Service (RADIUS)"
     27  *
     28  * RFC 2866:
     29  *      "RADIUS Accounting"
     30  *
     31  * RFC 2867:
     32  *      "RADIUS Accounting Modifications for Tunnel Protocol Support"
     33  *
     34  * RFC 2868:
     35  *      "RADIUS Attributes for Tunnel Protocol Support"
     36  *
     37  * RFC 2869:
     38  *      "RADIUS Extensions"
     39  *
     40  * RFC 3580:
     41  *      "IEEE 802.1X Remote Authentication Dial In User Service (RADIUS)"
     42  *      "Usage Guidelines"
     43  *
     44  * RFC 4675:
     45  *      "RADIUS Attributes for Virtual LAN and Priority Support"
     46  *
     47  * RFC 5176:
     48  *      "Dynamic Authorization Extensions to RADIUS"
     49  *
     50  * Alfredo Andres Omella (aandres (at) s21sec.com) v0.1 2000/09/15
     51  *
     52  * TODO: Among other things to print ok MacIntosh and Vendor values
     53  */
     54 
     55 #include <sys/cdefs.h>
     56 #ifndef lint
     57 __RCSID("$NetBSD: print-radius.c,v 1.7 2017/01/24 23:29:14 christos Exp $");
     58 #endif
     59 
     60 #ifdef HAVE_CONFIG_H
     61 #include "config.h"
     62 #endif
     63 
     64 #include <netdissect-stdinc.h>
     65 
     66 #include <string.h>
     67 
     68 #include "netdissect.h"
     69 #include "addrtoname.h"
     70 #include "extract.h"
     71 #include "oui.h"
     72 
     73 static const char tstr[] = " [|radius]";
     74 
     75 #define TAM_SIZE(x) (sizeof(x)/sizeof(x[0]) )
     76 
     77 #define PRINT_HEX(bytes_len, ptr_data)                               \
     78            while(bytes_len)                                          \
     79            {                                                         \
     80               ND_PRINT((ndo, "%02X", *ptr_data ));                   \
     81               ptr_data++;                                            \
     82               bytes_len--;                                           \
     83            }
     84 
     85 
     86 /* Radius packet codes */
     87 #define RADCMD_ACCESS_REQ   1 /* Access-Request      */
     88 #define RADCMD_ACCESS_ACC   2 /* Access-Accept       */
     89 #define RADCMD_ACCESS_REJ   3 /* Access-Reject       */
     90 #define RADCMD_ACCOUN_REQ   4 /* Accounting-Request  */
     91 #define RADCMD_ACCOUN_RES   5 /* Accounting-Response */
     92 #define RADCMD_ACCESS_CHA  11 /* Access-Challenge    */
     93 #define RADCMD_STATUS_SER  12 /* Status-Server       */
     94 #define RADCMD_STATUS_CLI  13 /* Status-Client       */
     95 #define RADCMD_DISCON_REQ  40 /* Disconnect-Request  */
     96 #define RADCMD_DISCON_ACK  41 /* Disconnect-ACK      */
     97 #define RADCMD_DISCON_NAK  42 /* Disconnect-NAK      */
     98 #define RADCMD_COA_REQ     43 /* CoA-Request         */
     99 #define RADCMD_COA_ACK     44 /* CoA-ACK             */
    100 #define RADCMD_COA_NAK     45 /* CoA-NAK             */
    101 #define RADCMD_RESERVED   255 /* Reserved            */
    102 
    103 static const struct tok radius_command_values[] = {
    104     { RADCMD_ACCESS_REQ, "Access-Request" },
    105     { RADCMD_ACCESS_ACC, "Access-Accept" },
    106     { RADCMD_ACCESS_REJ, "Access-Reject" },
    107     { RADCMD_ACCOUN_REQ, "Accounting-Request" },
    108     { RADCMD_ACCOUN_RES, "Accounting-Response" },
    109     { RADCMD_ACCESS_CHA, "Access-Challenge" },
    110     { RADCMD_STATUS_SER, "Status-Server" },
    111     { RADCMD_STATUS_CLI, "Status-Client" },
    112     { RADCMD_DISCON_REQ, "Disconnect-Request" },
    113     { RADCMD_DISCON_ACK, "Disconnect-ACK" },
    114     { RADCMD_DISCON_NAK, "Disconnect-NAK" },
    115     { RADCMD_COA_REQ,    "CoA-Request" },
    116     { RADCMD_COA_ACK,    "CoA-ACK" },
    117     { RADCMD_COA_NAK,    "CoA-NAK" },
    118     { RADCMD_RESERVED,   "Reserved" },
    119     { 0, NULL}
    120 };
    121 
    122 /********************************/
    123 /* Begin Radius Attribute types */
    124 /********************************/
    125 #define SERV_TYPE    6
    126 #define FRM_IPADDR   8
    127 #define LOG_IPHOST  14
    128 #define LOG_SERVICE 15
    129 #define FRM_IPX     23
    130 #define SESSION_TIMEOUT   27
    131 #define IDLE_TIMEOUT      28
    132 #define FRM_ATALK_LINK    37
    133 #define FRM_ATALK_NETWORK 38
    134 
    135 #define ACCT_DELAY        41
    136 #define ACCT_SESSION_TIME 46
    137 
    138 #define EGRESS_VLAN_ID   56
    139 #define EGRESS_VLAN_NAME 58
    140 
    141 #define TUNNEL_TYPE        64
    142 #define TUNNEL_MEDIUM      65
    143 #define TUNNEL_CLIENT_END  66
    144 #define TUNNEL_SERVER_END  67
    145 #define TUNNEL_PASS        69
    146 
    147 #define ARAP_PASS          70
    148 #define ARAP_FEATURES      71
    149 
    150 #define TUNNEL_PRIV_GROUP  81
    151 #define TUNNEL_ASSIGN_ID   82
    152 #define TUNNEL_PREFERENCE  83
    153 
    154 #define ARAP_CHALLENGE_RESP 84
    155 #define ACCT_INT_INTERVAL   85
    156 
    157 #define TUNNEL_CLIENT_AUTH 90
    158 #define TUNNEL_SERVER_AUTH 91
    159 /********************************/
    160 /* End Radius Attribute types */
    161 /********************************/
    162 
    163 #define RFC4675_TAGGED   0x31
    164 #define RFC4675_UNTAGGED 0x32
    165 
    166 static const struct tok rfc4675_tagged[] = {
    167     { RFC4675_TAGGED,   "Tagged" },
    168     { RFC4675_UNTAGGED, "Untagged" },
    169     { 0, NULL}
    170 };
    171 
    172 
    173 static void print_attr_string(netdissect_options *, register const u_char *, u_int, u_short );
    174 static void print_attr_num(netdissect_options *, register const u_char *, u_int, u_short );
    175 static void print_vendor_attr(netdissect_options *, register const u_char *, u_int, u_short );
    176 static void print_attr_address(netdissect_options *, register const u_char *, u_int, u_short);
    177 static void print_attr_time(netdissect_options *, register const u_char *, u_int, u_short);
    178 static void print_attr_strange(netdissect_options *, register const u_char *, u_int, u_short);
    179 
    180 
    181 struct radius_hdr { uint8_t  code; /* Radius packet code  */
    182                     uint8_t  id;   /* Radius packet id    */
    183                     uint16_t len;  /* Radius total length */
    184                     uint8_t  auth[16]; /* Authenticator   */
    185                   };
    186 
    187 #define MIN_RADIUS_LEN	20
    188 
    189 struct radius_attr { uint8_t type; /* Attribute type   */
    190                      uint8_t len;  /* Attribute length */
    191                    };
    192 
    193 
    194 /* Service-Type Attribute standard values */
    195 static const char *serv_type[]={ NULL,
    196                                 "Login",
    197                                 "Framed",
    198                                 "Callback Login",
    199                                 "Callback Framed",
    200                                 "Outbound",
    201                                 "Administrative",
    202                                 "NAS Prompt",
    203                                 "Authenticate Only",
    204                                 "Callback NAS Prompt",
    205                                 "Call Check",
    206                                 "Callback Administrative",
    207                                };
    208 
    209 /* Framed-Protocol Attribute standard values */
    210 static const char *frm_proto[]={ NULL,
    211                                  "PPP",
    212                                  "SLIP",
    213                                  "ARAP",
    214                                  "Gandalf proprietary",
    215                                  "Xylogics IPX/SLIP",
    216                                  "X.75 Synchronous",
    217                                };
    218 
    219 /* Framed-Routing Attribute standard values */
    220 static const char *frm_routing[]={ "None",
    221                                    "Send",
    222                                    "Listen",
    223                                    "Send&Listen",
    224                                  };
    225 
    226 /* Framed-Compression Attribute standard values */
    227 static const char *frm_comp[]={ "None",
    228                                 "VJ TCP/IP",
    229                                 "IPX",
    230                                 "Stac-LZS",
    231                               };
    232 
    233 /* Login-Service Attribute standard values */
    234 static const char *login_serv[]={ "Telnet",
    235                                   "Rlogin",
    236                                   "TCP Clear",
    237                                   "PortMaster(proprietary)",
    238                                   "LAT",
    239                                   "X.25-PAD",
    240                                   "X.25-T3POS",
    241                                   "Unassigned",
    242                                   "TCP Clear Quiet",
    243                                 };
    244 
    245 
    246 /* Termination-Action Attribute standard values */
    247 static const char *term_action[]={ "Default",
    248                                    "RADIUS-Request",
    249                                  };
    250 
    251 /* Ingress-Filters Attribute standard values */
    252 static const char *ingress_filters[]={ NULL,
    253                                        "Enabled",
    254                                        "Disabled",
    255                                      };
    256 
    257 /* NAS-Port-Type Attribute standard values */
    258 static const char *nas_port_type[]={ "Async",
    259                                      "Sync",
    260                                      "ISDN Sync",
    261                                      "ISDN Async V.120",
    262                                      "ISDN Async V.110",
    263                                      "Virtual",
    264                                      "PIAFS",
    265                                      "HDLC Clear Channel",
    266                                      "X.25",
    267                                      "X.75",
    268                                      "G.3 Fax",
    269                                      "SDSL",
    270                                      "ADSL-CAP",
    271                                      "ADSL-DMT",
    272                                      "ISDN-DSL",
    273                                      "Ethernet",
    274                                      "xDSL",
    275                                      "Cable",
    276                                      "Wireless - Other",
    277                                      "Wireless - IEEE 802.11",
    278                                    };
    279 
    280 /* Acct-Status-Type Accounting Attribute standard values */
    281 static const char *acct_status[]={ NULL,
    282                                    "Start",
    283                                    "Stop",
    284                                    "Interim-Update",
    285                                    "Unassigned",
    286                                    "Unassigned",
    287                                    "Unassigned",
    288                                    "Accounting-On",
    289                                    "Accounting-Off",
    290                                    "Tunnel-Start",
    291                                    "Tunnel-Stop",
    292                                    "Tunnel-Reject",
    293                                    "Tunnel-Link-Start",
    294                                    "Tunnel-Link-Stop",
    295                                    "Tunnel-Link-Reject",
    296                                    "Failed",
    297                                  };
    298 
    299 /* Acct-Authentic Accounting Attribute standard values */
    300 static const char *acct_auth[]={ NULL,
    301                                  "RADIUS",
    302                                  "Local",
    303                                  "Remote",
    304                                };
    305 
    306 /* Acct-Terminate-Cause Accounting Attribute standard values */
    307 static const char *acct_term[]={ NULL,
    308                                  "User Request",
    309                                  "Lost Carrier",
    310                                  "Lost Service",
    311                                  "Idle Timeout",
    312                                  "Session Timeout",
    313                                  "Admin Reset",
    314                                  "Admin Reboot",
    315                                  "Port Error",
    316                                  "NAS Error",
    317                                  "NAS Request",
    318                                  "NAS Reboot",
    319                                  "Port Unneeded",
    320                                  "Port Preempted",
    321                                  "Port Suspended",
    322                                  "Service Unavailable",
    323                                  "Callback",
    324                                  "User Error",
    325                                  "Host Request",
    326                                };
    327 
    328 /* Tunnel-Type Attribute standard values */
    329 static const char *tunnel_type[]={ NULL,
    330                                    "PPTP",
    331                                    "L2F",
    332                                    "L2TP",
    333                                    "ATMP",
    334                                    "VTP",
    335                                    "AH",
    336                                    "IP-IP",
    337                                    "MIN-IP-IP",
    338                                    "ESP",
    339                                    "GRE",
    340                                    "DVS",
    341                                    "IP-in-IP Tunneling",
    342                                    "VLAN",
    343                                  };
    344 
    345 /* Tunnel-Medium-Type Attribute standard values */
    346 static const char *tunnel_medium[]={ NULL,
    347                                      "IPv4",
    348                                      "IPv6",
    349                                      "NSAP",
    350                                      "HDLC",
    351                                      "BBN 1822",
    352                                      "802",
    353                                      "E.163",
    354                                      "E.164",
    355                                      "F.69",
    356                                      "X.121",
    357                                      "IPX",
    358                                      "Appletalk",
    359                                      "Decnet IV",
    360                                      "Banyan Vines",
    361                                      "E.164 with NSAP subaddress",
    362                                    };
    363 
    364 /* ARAP-Zone-Access Attribute standard values */
    365 static const char *arap_zone[]={ NULL,
    366                                  "Only access to dfl zone",
    367                                  "Use zone filter inc.",
    368                                  "Not used",
    369                                  "Use zone filter exc.",
    370                                };
    371 
    372 static const char *prompt[]={ "No Echo",
    373                               "Echo",
    374                             };
    375 
    376 
    377 struct attrtype { const char *name;      /* Attribute name                 */
    378                   const char **subtypes; /* Standard Values (if any)       */
    379                   u_char siz_subtypes;   /* Size of total standard values  */
    380                   u_char first_subtype;  /* First standard value is 0 or 1 */
    381                   void (*print_func)(netdissect_options *, register const u_char *, u_int, u_short);
    382                 } attr_type[]=
    383   {
    384      { NULL,                              NULL, 0, 0, NULL               },
    385      { "User-Name",                       NULL, 0, 0, print_attr_string  },
    386      { "User-Password",                   NULL, 0, 0, NULL               },
    387      { "CHAP-Password",                   NULL, 0, 0, NULL               },
    388      { "NAS-IP-Address",                  NULL, 0, 0, print_attr_address },
    389      { "NAS-Port",                        NULL, 0, 0, print_attr_num     },
    390      { "Service-Type",                    serv_type, TAM_SIZE(serv_type)-1, 1, print_attr_num },
    391      { "Framed-Protocol",                 frm_proto, TAM_SIZE(frm_proto)-1, 1, print_attr_num },
    392      { "Framed-IP-Address",               NULL, 0, 0, print_attr_address },
    393      { "Framed-IP-Netmask",               NULL, 0, 0, print_attr_address },
    394      { "Framed-Routing",                  frm_routing, TAM_SIZE(frm_routing), 0, print_attr_num },
    395      { "Filter-Id",                       NULL, 0, 0, print_attr_string  },
    396      { "Framed-MTU",                      NULL, 0, 0, print_attr_num     },
    397      { "Framed-Compression",              frm_comp, TAM_SIZE(frm_comp),   0, print_attr_num },
    398      { "Login-IP-Host",                   NULL, 0, 0, print_attr_address },
    399      { "Login-Service",                   login_serv, TAM_SIZE(login_serv), 0, print_attr_num },
    400      { "Login-TCP-Port",                  NULL, 0, 0, print_attr_num     },
    401      { "Unassigned",                      NULL, 0, 0, NULL }, /*17*/
    402      { "Reply-Message",                   NULL, 0, 0, print_attr_string },
    403      { "Callback-Number",                 NULL, 0, 0, print_attr_string },
    404      { "Callback-Id",                     NULL, 0, 0, print_attr_string },
    405      { "Unassigned",                      NULL, 0, 0, NULL }, /*21*/
    406      { "Framed-Route",                    NULL, 0, 0, print_attr_string },
    407      { "Framed-IPX-Network",              NULL, 0, 0, print_attr_num    },
    408      { "State",                           NULL, 0, 0, print_attr_string },
    409      { "Class",                           NULL, 0, 0, print_attr_string },
    410      { "Vendor-Specific",                 NULL, 0, 0, print_vendor_attr },
    411      { "Session-Timeout",                 NULL, 0, 0, print_attr_num    },
    412      { "Idle-Timeout",                    NULL, 0, 0, print_attr_num    },
    413      { "Termination-Action",              term_action, TAM_SIZE(term_action), 0, print_attr_num },
    414      { "Called-Station-Id",               NULL, 0, 0, print_attr_string },
    415      { "Calling-Station-Id",              NULL, 0, 0, print_attr_string },
    416      { "NAS-Identifier",                  NULL, 0, 0, print_attr_string },
    417      { "Proxy-State",                     NULL, 0, 0, print_attr_string },
    418      { "Login-LAT-Service",               NULL, 0, 0, print_attr_string },
    419      { "Login-LAT-Node",                  NULL, 0, 0, print_attr_string },
    420      { "Login-LAT-Group",                 NULL, 0, 0, print_attr_string },
    421      { "Framed-AppleTalk-Link",           NULL, 0, 0, print_attr_num    },
    422      { "Framed-AppleTalk-Network",        NULL, 0, 0, print_attr_num    },
    423      { "Framed-AppleTalk-Zone",           NULL, 0, 0, print_attr_string },
    424      { "Acct-Status-Type",                acct_status, TAM_SIZE(acct_status)-1, 1, print_attr_num },
    425      { "Acct-Delay-Time",                 NULL, 0, 0, print_attr_num    },
    426      { "Acct-Input-Octets",               NULL, 0, 0, print_attr_num    },
    427      { "Acct-Output-Octets",              NULL, 0, 0, print_attr_num    },
    428      { "Acct-Session-Id",                 NULL, 0, 0, print_attr_string },
    429      { "Acct-Authentic",                  acct_auth, TAM_SIZE(acct_auth)-1, 1, print_attr_num },
    430      { "Acct-Session-Time",               NULL, 0, 0, print_attr_num },
    431      { "Acct-Input-Packets",              NULL, 0, 0, print_attr_num },
    432      { "Acct-Output-Packets",             NULL, 0, 0, print_attr_num },
    433      { "Acct-Terminate-Cause",            acct_term, TAM_SIZE(acct_term)-1, 1, print_attr_num },
    434      { "Acct-Multi-Session-Id",           NULL, 0, 0, print_attr_string },
    435      { "Acct-Link-Count",                 NULL, 0, 0, print_attr_num },
    436      { "Acct-Input-Gigawords",            NULL, 0, 0, print_attr_num },
    437      { "Acct-Output-Gigawords",           NULL, 0, 0, print_attr_num },
    438      { "Unassigned",                      NULL, 0, 0, NULL }, /*54*/
    439      { "Event-Timestamp",                 NULL, 0, 0, print_attr_time },
    440      { "Egress-VLANID",                   NULL, 0, 0, print_attr_num },
    441      { "Ingress-Filters",                 ingress_filters, TAM_SIZE(ingress_filters)-1, 1, print_attr_num },
    442      { "Egress-VLAN-Name",                NULL, 0, 0, print_attr_string },
    443      { "User-Priority-Table",             NULL, 0, 0, NULL },
    444      { "CHAP-Challenge",                  NULL, 0, 0, print_attr_string },
    445      { "NAS-Port-Type",                   nas_port_type, TAM_SIZE(nas_port_type), 0, print_attr_num },
    446      { "Port-Limit",                      NULL, 0, 0, print_attr_num },
    447      { "Login-LAT-Port",                  NULL, 0, 0, print_attr_string }, /*63*/
    448      { "Tunnel-Type",                     tunnel_type, TAM_SIZE(tunnel_type)-1, 1, print_attr_num },
    449      { "Tunnel-Medium-Type",              tunnel_medium, TAM_SIZE(tunnel_medium)-1, 1, print_attr_num },
    450      { "Tunnel-Client-Endpoint",          NULL, 0, 0, print_attr_string },
    451      { "Tunnel-Server-Endpoint",          NULL, 0, 0, print_attr_string },
    452      { "Acct-Tunnel-Connection",          NULL, 0, 0, print_attr_string },
    453      { "Tunnel-Password",                 NULL, 0, 0, print_attr_string  },
    454      { "ARAP-Password",                   NULL, 0, 0, print_attr_strange },
    455      { "ARAP-Features",                   NULL, 0, 0, print_attr_strange },
    456      { "ARAP-Zone-Access",                arap_zone, TAM_SIZE(arap_zone)-1, 1, print_attr_num }, /*72*/
    457      { "ARAP-Security",                   NULL, 0, 0, print_attr_string },
    458      { "ARAP-Security-Data",              NULL, 0, 0, print_attr_string },
    459      { "Password-Retry",                  NULL, 0, 0, print_attr_num    },
    460      { "Prompt",                          prompt, TAM_SIZE(prompt), 0, print_attr_num },
    461      { "Connect-Info",                    NULL, 0, 0, print_attr_string   },
    462      { "Configuration-Token",             NULL, 0, 0, print_attr_string   },
    463      { "EAP-Message",                     NULL, 0, 0, print_attr_string   },
    464      { "Message-Authenticator",           NULL, 0, 0, print_attr_string }, /*80*/
    465      { "Tunnel-Private-Group-ID",         NULL, 0, 0, print_attr_string },
    466      { "Tunnel-Assignment-ID",            NULL, 0, 0, print_attr_string },
    467      { "Tunnel-Preference",               NULL, 0, 0, print_attr_num    },
    468      { "ARAP-Challenge-Response",         NULL, 0, 0, print_attr_strange },
    469      { "Acct-Interim-Interval",           NULL, 0, 0, print_attr_num     },
    470      { "Acct-Tunnel-Packets-Lost",        NULL, 0, 0, print_attr_num }, /*86*/
    471      { "NAS-Port-Id",                     NULL, 0, 0, print_attr_string },
    472      { "Framed-Pool",                     NULL, 0, 0, print_attr_string },
    473      { "CUI",                             NULL, 0, 0, print_attr_string },
    474      { "Tunnel-Client-Auth-ID",           NULL, 0, 0, print_attr_string },
    475      { "Tunnel-Server-Auth-ID",           NULL, 0, 0, print_attr_string },
    476      { "Unassigned",                      NULL, 0, 0, NULL }, /*92*/
    477      { "Unassigned",                      NULL, 0, 0, NULL }  /*93*/
    478   };
    479 
    480 
    481 /*****************************/
    482 /* Print an attribute string */
    483 /* value pointed by 'data'   */
    484 /* and 'length' size.        */
    485 /*****************************/
    486 /* Returns nothing.          */
    487 /*****************************/
    488 static void
    489 print_attr_string(netdissect_options *ndo,
    490                   register const u_char *data, u_int length, u_short attr_code)
    491 {
    492    register u_int i;
    493 
    494    ND_TCHECK2(data[0],length);
    495 
    496    switch(attr_code)
    497    {
    498       case TUNNEL_PASS:
    499            if (length < 3)
    500            {
    501               ND_PRINT((ndo, "%s", tstr));
    502               return;
    503            }
    504            if (*data && (*data <=0x1F) )
    505               ND_PRINT((ndo, "Tag[%u] ", *data));
    506            else
    507               ND_PRINT((ndo, "Tag[Unused] "));
    508            data++;
    509            length--;
    510            ND_PRINT((ndo, "Salt %u ", EXTRACT_16BITS(data)));
    511            data+=2;
    512            length-=2;
    513         break;
    514       case TUNNEL_CLIENT_END:
    515       case TUNNEL_SERVER_END:
    516       case TUNNEL_PRIV_GROUP:
    517       case TUNNEL_ASSIGN_ID:
    518       case TUNNEL_CLIENT_AUTH:
    519       case TUNNEL_SERVER_AUTH:
    520            if (*data <= 0x1F)
    521            {
    522               if (length < 1)
    523               {
    524                  ND_PRINT((ndo, "%s", tstr));
    525                  return;
    526               }
    527               if (*data)
    528                 ND_PRINT((ndo, "Tag[%u] ", *data));
    529               else
    530                 ND_PRINT((ndo, "Tag[Unused] "));
    531               data++;
    532               length--;
    533            }
    534         break;
    535       case EGRESS_VLAN_NAME:
    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; *data && i < length ; 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