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