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