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