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