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