]> The Tcpdump Group git mirrors - tcpdump/blob - print-radius.c
Use more the EXTRACT_U_1() macro (51/n)
[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((ndo, "%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 *, register const u_char *, u_int, u_short );
195 static void print_attr_num(netdissect_options *, register const u_char *, u_int, u_short );
196 static void print_vendor_attr(netdissect_options *, register const u_char *, u_int, u_short );
197 static void print_attr_address(netdissect_options *, register const u_char *, u_int, u_short);
198 static void print_attr_address6(netdissect_options *, register const u_char *, u_int, u_short);
199 static void print_attr_netmask6(netdissect_options *, register const u_char *, u_int, u_short);
200 static void print_attr_time(netdissect_options *, register const u_char *, u_int, u_short);
201 static void print_attr_strange(netdissect_options *, register const u_char *, u_int, u_short);
202
203
204 struct radius_hdr { uint8_t code; /* Radius packet code */
205 uint8_t id; /* Radius packet id */
206 uint16_t len; /* Radius total length */
207 uint8_t auth[16]; /* Authenticator */
208 };
209
210 #define MIN_RADIUS_LEN 20
211
212 struct radius_attr { uint8_t type; /* Attribute type */
213 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 *, register 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 register const u_char *data, u_int length, u_short attr_code)
586 {
587 register u_int i;
588
589 ND_TCHECK2(data[0],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((ndo, "Tag[%u] ", EXTRACT_U_1(data)));
598 else
599 ND_PRINT((ndo, "Tag[Unused] "));
600 data++;
601 length--;
602 ND_PRINT((ndo, "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((ndo, "Tag[%u] ", EXTRACT_U_1(data)));
618 else
619 ND_PRINT((ndo, "Tag[Unused] "));
620 data++;
621 length--;
622 }
623 break;
624 case EGRESS_VLAN_NAME:
625 if (length < 1)
626 goto trunc;
627 ND_PRINT((ndo, "%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((ndo, "%c", ND_ISPRINT(EXTRACT_U_1(data)) ? EXTRACT_U_1(data) : '.'));
637
638 return;
639
640 trunc:
641 ND_PRINT((ndo, "%s", tstr));
642 }
643
644 /*
645 * print vendor specific attributes
646 */
647 static void
648 print_vendor_attr(netdissect_options *ndo,
649 register 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((ndo, "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((ndo, "\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((ndo, "\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_TCHECK2(*data, vendor_length);
691
692 ND_PRINT((ndo, "\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((ndo, "%c", ND_ISPRINT(EXTRACT_U_1(data)) ? EXTRACT_U_1(data) : '.'));
697 length-=vendor_length;
698 }
699 return;
700
701 trunc:
702 ND_PRINT((ndo, "%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 register 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((ndo, "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((ndo, "Tag[Unused] "));
736 else
737 ND_PRINT((ndo, "Tag[%d] ", 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((ndo, "%s", table[data_value]));
749 else
750 ND_PRINT((ndo, "#%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((ndo, "NAS Select"));
759 else
760 ND_PRINT((ndo, "%d", 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((ndo, "%02d secs", timeout));
771 else
772 {
773 if ( timeout < 3600 )
774 ND_PRINT((ndo, "%02d:%02d min",
775 timeout / 60, timeout % 60));
776 else
777 ND_PRINT((ndo, "%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((ndo, "%d", EXTRACT_BE_U_4(data)));
786 else
787 ND_PRINT((ndo, "Unnumbered"));
788 break;
789
790 case FRM_ATALK_NETWORK:
791 if (EXTRACT_BE_U_4(data))
792 ND_PRINT((ndo, "%d", EXTRACT_BE_U_4(data)));
793 else
794 ND_PRINT((ndo, "NAS assigned"));
795 break;
796
797 case TUNNEL_PREFERENCE:
798 if (EXTRACT_U_1(data))
799 ND_PRINT((ndo, "Tag[%d] ", EXTRACT_U_1(data)));
800 else
801 ND_PRINT((ndo, "Tag[Unused] "));
802 data++;
803 ND_PRINT((ndo, "%d", EXTRACT_BE_U_3(data)));
804 break;
805
806 case EGRESS_VLAN_ID:
807 ND_PRINT((ndo, "%s (0x%02x) ",
808 tok2str(rfc4675_tagged,"Unknown tag",EXTRACT_U_1(data)),
809 EXTRACT_U_1(data)));
810 data++;
811 ND_PRINT((ndo, "%d", EXTRACT_BE_U_3(data)));
812 break;
813
814 default:
815 ND_PRINT((ndo, "%d", EXTRACT_BE_U_4(data)));
816 break;
817
818 } /* switch */
819
820 } /* if-else */
821
822 return;
823
824 trunc:
825 ND_PRINT((ndo, "%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 register const u_char *data, u_int length, u_short attr_code)
838 {
839 if (length != 4)
840 {
841 ND_PRINT((ndo, "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((ndo, "User Selected"));
853 else
854 if (EXTRACT_BE_U_4(data) == 0xFFFFFFFE )
855 ND_PRINT((ndo, "NAS Select"));
856 else
857 ND_PRINT((ndo, "%s",ipaddr_string(ndo, data)));
858 break;
859
860 default:
861 ND_PRINT((ndo, "%s", ipaddr_string(ndo, data)));
862 break;
863 }
864
865 return;
866
867 trunc:
868 ND_PRINT((ndo, "%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 register const u_char *data, u_int length, u_short attr_code _U_)
881 {
882 if (length != 16)
883 {
884 ND_PRINT((ndo, "ERROR: length %u != 16", length));
885 return;
886 }
887
888 ND_TCHECK_16(data);
889
890 ND_PRINT((ndo, "%s", ip6addr_string(ndo, data)));
891
892 return;
893
894 trunc:
895 ND_PRINT((ndo, "%s", tstr));
896 }
897
898 static void
899 print_attr_netmask6(netdissect_options *ndo,
900 register 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((ndo, "ERROR: length %u not in range (2..18)", length));
907 return;
908 }
909 ND_TCHECK2(data[0], length);
910 if (EXTRACT_U_1(data + 1) > 128)
911 {
912 ND_PRINT((ndo, "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((ndo, "%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((ndo, " (inconsistent prefix length)"));
924
925 return;
926
927 trunc:
928 ND_PRINT((ndo, "%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 register 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((ndo, "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((ndo, "%.24s", string));
959 return;
960
961 trunc:
962 ND_PRINT((ndo, "%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 register 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((ndo, "ERROR: length %u != 16", length));
985 return;
986 }
987 ND_PRINT((ndo, "User_challenge ("));
988 ND_TCHECK_8(data);
989 len_data = 8;
990 PRINT_HEX(len_data, data);
991 ND_PRINT((ndo, ") User_resp("));
992 ND_TCHECK_8(data);
993 len_data = 8;
994 PRINT_HEX(len_data, data);
995 ND_PRINT((ndo, ")"));
996 break;
997
998 case ARAP_FEATURES:
999 if (length != 14)
1000 {
1001 ND_PRINT((ndo, "ERROR: length %u != 14", length));
1002 return;
1003 }
1004 ND_TCHECK_1(data);
1005 if (EXTRACT_U_1(data))
1006 ND_PRINT((ndo, "User can change password"));
1007 else
1008 ND_PRINT((ndo, "User cannot change password"));
1009 data++;
1010 ND_TCHECK_1(data);
1011 ND_PRINT((ndo, ", Min password length: %d", EXTRACT_U_1(data)));
1012 data++;
1013 ND_PRINT((ndo, ", created at: "));
1014 ND_TCHECK_4(data);
1015 len_data = 4;
1016 PRINT_HEX(len_data, data);
1017 ND_PRINT((ndo, ", expires in: "));
1018 ND_TCHECK_4(data);
1019 len_data = 4;
1020 PRINT_HEX(len_data, data);
1021 ND_PRINT((ndo, ", 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((ndo, "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((ndo, "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((ndo, "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((ndo, "%s", tstr));
1054 }
1055
1056 static void
1057 radius_attrs_print(netdissect_options *ndo,
1058 register const u_char *attr, u_int length)
1059 {
1060 register const struct radius_attr *rad_attr = (const struct radius_attr *)attr;
1061 const char *attr_string;
1062
1063 while (length > 0)
1064 {
1065 if (length < 2)
1066 goto trunc;
1067 ND_TCHECK(*rad_attr);
1068
1069 if (rad_attr->type > 0 && rad_attr->type < TAM_SIZE(attr_type))
1070 attr_string = attr_type[rad_attr->type].name;
1071 else
1072 attr_string = "Unknown";
1073 if (rad_attr->len < 2)
1074 {
1075 ND_PRINT((ndo, "\n\t %s Attribute (%u), length: %u (bogus, must be >= 2)",
1076 attr_string,
1077 rad_attr->type,
1078 rad_attr->len));
1079 return;
1080 }
1081 if (rad_attr->len > length)
1082 {
1083 ND_PRINT((ndo, "\n\t %s Attribute (%u), length: %u (bogus, goes past end of packet)",
1084 attr_string,
1085 rad_attr->type,
1086 rad_attr->len));
1087 return;
1088 }
1089 ND_PRINT((ndo, "\n\t %s Attribute (%u), length: %u, Value: ",
1090 attr_string,
1091 rad_attr->type,
1092 rad_attr->len));
1093
1094 if (rad_attr->type < TAM_SIZE(attr_type))
1095 {
1096 if (rad_attr->len > 2)
1097 {
1098 if ( attr_type[rad_attr->type].print_func )
1099 (*attr_type[rad_attr->type].print_func)(
1100 ndo, ((const u_char *)(rad_attr+1)),
1101 rad_attr->len - 2, rad_attr->type);
1102 }
1103 }
1104 /* do we also want to see a hex dump ? */
1105 if (ndo->ndo_vflag> 1)
1106 print_unknown_data(ndo, (const u_char *)rad_attr+2, "\n\t ", (rad_attr->len)-2);
1107
1108 length-=(rad_attr->len);
1109 rad_attr = (const struct radius_attr *)( ((const char *)(rad_attr))+rad_attr->len);
1110 }
1111 return;
1112
1113 trunc:
1114 ND_PRINT((ndo, "%s", tstr));
1115 }
1116
1117 void
1118 radius_print(netdissect_options *ndo,
1119 const u_char *dat, u_int length)
1120 {
1121 register const struct radius_hdr *rad;
1122 u_int len, auth_idx;
1123
1124 ND_TCHECK2(*dat, MIN_RADIUS_LEN);
1125 rad = (const struct radius_hdr *)dat;
1126 len = EXTRACT_BE_U_2(&rad->len);
1127
1128 if (len < MIN_RADIUS_LEN)
1129 {
1130 ND_PRINT((ndo, "%s", tstr));
1131 return;
1132 }
1133
1134 if (len > length)
1135 len = length;
1136
1137 if (ndo->ndo_vflag < 1) {
1138 ND_PRINT((ndo, "RADIUS, %s (%u), id: 0x%02x length: %u",
1139 tok2str(radius_command_values,"Unknown Command",rad->code),
1140 rad->code,
1141 rad->id,
1142 len));
1143 return;
1144 }
1145 else {
1146 ND_PRINT((ndo, "RADIUS, length: %u\n\t%s (%u), id: 0x%02x, Authenticator: ",
1147 len,
1148 tok2str(radius_command_values,"Unknown Command",rad->code),
1149 rad->code,
1150 rad->id));
1151
1152 for(auth_idx=0; auth_idx < 16; auth_idx++)
1153 ND_PRINT((ndo, "%02x", rad->auth[auth_idx]));
1154 }
1155
1156 if (len > MIN_RADIUS_LEN)
1157 radius_attrs_print(ndo, dat + MIN_RADIUS_LEN, len - MIN_RADIUS_LEN);
1158 return;
1159
1160 trunc:
1161 ND_PRINT((ndo, "%s", tstr));
1162 }