xref: /freebsd/contrib/tcpdump/print-radius.c (revision 1e413cf93298b5b97441a21d9a50fdcd0ee9945e)
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.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 
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 
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 /***********************************/
761 static 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 
832 static void
833 radius_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 
888 trunc:
889    printf(" [|radius]");
890 }
891 
892 
893 void
894 radius_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 
935 trunc:
936    printf(" [|radius]");
937 }
938