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