xref: /netbsd-src/external/bsd/tcpdump/dist/print-radius.c (revision ba65fde2d7fefa7d39838fa5fa855e62bd606b5e)
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
46 static const char rcsid[] _U_ =
47     "Id: print-radius.c,v 1.28 2005-09-26 01:01:55 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 
87 static 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 
139 static void print_attr_string(register u_char *, u_int, u_short );
140 static void print_attr_num(register u_char *, u_int, u_short );
141 static void print_vendor_attr(register u_char *, u_int, u_short );
142 static void print_attr_address(register u_char *, u_int, u_short);
143 static void print_attr_time(register u_char *, u_int, u_short);
144 static void print_attr_strange(register u_char *, u_int, u_short);
145 
146 
147 struct 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 
155 struct radius_attr { u_int8_t type; /* Attribute type   */
156                      u_int8_t len;  /* Attribute length */
157                    };
158 
159 
160 /* Service-Type Attribute standard values */
161 static 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 */
176 static 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 */
186 static const char *frm_routing[]={ "None",
187                                    "Send",
188                                    "Listen",
189                                    "Send&Listen",
190                                  };
191 
192 /* Framed-Compression Attribute standard values */
193 static const char *frm_comp[]={ "None",
194                                 "VJ TCP/IP",
195                                 "IPX",
196                                 "Stac-LZS",
197                               };
198 
199 /* Login-Service Attribute standard values */
200 static 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 */
213 static const char *term_action[]={ "Default",
214                                    "RADIUS-Request",
215                                  };
216 
217 /* NAS-Port-Type Attribute standard values */
218 static 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 */
241 static 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 */
260 static const char *acct_auth[]={ NULL,
261                                  "RADIUS",
262                                  "Local",
263                                  "Remote",
264                                };
265 
266 /* Acct-Terminate-Cause Accounting Attribute standard values */
267 static 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 */
289 static 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 */
305 static 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 */
324 static 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 
331 static const char *prompt[]={ "No Echo",
332                               "Echo",
333                             };
334 
335 
336 struct 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 /*****************************/
447 static void
448 print_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 
503 static void
504 print_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 /******************************/
569 static void
570 print_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 /*****************************/
685 static void
686 print_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 /*************************************/
729 static 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    const char *p;
734 
735    if (length != 4)
736    {
737        printf("ERROR: length %u != 4", length);
738        return;
739    }
740 
741    TCHECK2(data[0],4);
742 
743    attr_time = EXTRACT_32BITS(data);
744    if ((p = ctime(&attr_time)) == NULL)
745 	p = "?";
746    strlcpy(string, p, sizeof(string));
747    /* Get rid of the newline */
748    string[24] = '\0';
749    printf("%.24s", string);
750    return;
751 
752    trunc:
753      printf(" [|radius]");
754 }
755 
756 
757 /***********************************/
758 /* Print an attribute of 'strange' */
759 /* data format pointed by 'data'   */
760 /* and 'length' size.              */
761 /***********************************/
762 /* Returns nothing.                */
763 /***********************************/
764 static void print_attr_strange(register u_char *data, u_int length, u_short attr_code)
765 {
766    u_short len_data;
767 
768    switch(attr_code)
769    {
770       case ARAP_PASS:
771            if (length != 16)
772            {
773                printf("ERROR: length %u != 16", length);
774                return;
775            }
776            printf("User_challenge (");
777            TCHECK2(data[0],8);
778            len_data = 8;
779            PRINT_HEX(len_data, data);
780            printf(") User_resp(");
781            TCHECK2(data[0],8);
782            len_data = 8;
783            PRINT_HEX(len_data, data);
784            printf(")");
785         break;
786 
787       case ARAP_FEATURES:
788            if (length != 14)
789            {
790                printf("ERROR: length %u != 14", length);
791                return;
792            }
793            TCHECK2(data[0],1);
794            if (*data)
795               printf("User can change password");
796            else
797               printf("User cannot change password");
798            data++;
799            TCHECK2(data[0],1);
800            printf(", Min password length: %d",*data);
801            data++;
802            printf(", created at: ");
803            TCHECK2(data[0],4);
804            len_data = 4;
805            PRINT_HEX(len_data, data);
806            printf(", expires in: ");
807            TCHECK2(data[0],4);
808            len_data = 4;
809            PRINT_HEX(len_data, data);
810            printf(", Current Time: ");
811            TCHECK2(data[0],4);
812            len_data = 4;
813            PRINT_HEX(len_data, data);
814         break;
815 
816       case ARAP_CHALLENGE_RESP:
817            if (length < 8)
818            {
819                printf("ERROR: length %u != 8", length);
820                return;
821            }
822            TCHECK2(data[0],8);
823            len_data = 8;
824            PRINT_HEX(len_data, data);
825         break;
826    }
827    return;
828 
829    trunc:
830      printf(" [|radius]");
831 }
832 
833 
834 
835 static void
836 radius_attrs_print(register const u_char *attr, u_int length)
837 {
838    register const struct radius_attr *rad_attr = (struct radius_attr *)attr;
839    const char *attr_string;
840 
841    while (length > 0)
842    {
843      if (length < 2)
844         goto trunc;
845      TCHECK(*rad_attr);
846 
847      if (rad_attr->type > 0 && rad_attr->type < TAM_SIZE(attr_type))
848 	attr_string = attr_type[rad_attr->type].name;
849      else
850 	attr_string = "Unknown";
851      if (rad_attr->len < 2)
852      {
853 	printf("\n\t  %s Attribute (%u), length: %u (bogus, must be >= 2)",
854                attr_string,
855                rad_attr->type,
856                rad_attr->len);
857 	return;
858      }
859      if (rad_attr->len > length)
860      {
861 	printf("\n\t  %s Attribute (%u), length: %u (bogus, goes past end of packet)",
862                attr_string,
863                rad_attr->type,
864                rad_attr->len);
865         return;
866      }
867      printf("\n\t  %s Attribute (%u), length: %u, Value: ",
868             attr_string,
869             rad_attr->type,
870             rad_attr->len);
871 
872      if (rad_attr->type < TAM_SIZE(attr_type))
873      {
874          if (rad_attr->len > 2)
875          {
876              if ( attr_type[rad_attr->type].print_func )
877                  (*attr_type[rad_attr->type].print_func)(
878                      ((u_char *)(rad_attr+1)),
879                      rad_attr->len - 2, rad_attr->type);
880          }
881      }
882      /* do we also want to see a hex dump ? */
883      if (vflag> 1)
884          print_unknown_data((u_char *)rad_attr+2,"\n\t    ",(rad_attr->len)-2);
885 
886      length-=(rad_attr->len);
887      rad_attr = (struct radius_attr *)( ((char *)(rad_attr))+rad_attr->len);
888    }
889    return;
890 
891 trunc:
892    printf(" [|radius]");
893 }
894 
895 
896 void
897 radius_print(const u_char *dat, u_int length)
898 {
899    register const struct radius_hdr *rad;
900    u_int len, auth_idx;
901 
902    TCHECK2(*dat, MIN_RADIUS_LEN);
903    rad = (struct radius_hdr *)dat;
904    len = EXTRACT_16BITS(&rad->len);
905 
906    if (len < MIN_RADIUS_LEN)
907    {
908 	  printf(" [|radius]");
909 	  return;
910    }
911 
912    if (len > length)
913 	  len = length;
914 
915    if (vflag < 1) {
916        printf("RADIUS, %s (%u), id: 0x%02x length: %u",
917               tok2str(radius_command_values,"Unknown Command",rad->code),
918               rad->code,
919               rad->id,
920               len);
921        return;
922    }
923    else {
924        printf("RADIUS, length: %u\n\t%s (%u), id: 0x%02x, Authenticator: ",
925               len,
926               tok2str(radius_command_values,"Unknown Command",rad->code),
927               rad->code,
928               rad->id);
929 
930        for(auth_idx=0; auth_idx < 16; auth_idx++)
931             printf("%02x", rad->auth[auth_idx] );
932    }
933 
934    if (len > MIN_RADIUS_LEN)
935       radius_attrs_print( dat + MIN_RADIUS_LEN, len - MIN_RADIUS_LEN);
936    return;
937 
938 trunc:
939    printf(" [|radius]");
940 }
941