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