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