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